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.value()](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.value()](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.value()](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.value()](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.value()](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.value()](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): "
330 << m_minNPixelHitsPhysical );
331 trackCuts["PixelHits"].push_back([minNPixelHitsPhysical = m_minNPixelHitsPhysical.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
332 return getSummary(helper, msgHelper, xAOD::numberOfPixelHits) >= minNPixelHitsPhysical;
333 });
334 }
335 if (maxIntIsSet(m_maxNPixelHoles)) {
336 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum pixel holes: " << m_maxNPixelHoles );
337 trackCuts["PixelHits"].push_back([maxNPixelHoles = m_maxNPixelHoles.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
338 return getSummary(helper, msgHelper, xAOD::numberOfPixelHoles) <= maxNPixelHoles;
339 });
340 }
341 if (maxIntIsSet(m_maxNPixelSharedHits)) {
342 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum pixel shared hits: " << m_maxNPixelSharedHits );
343 trackCuts["PixelHits"].push_back([maxNPixelSharedHits = m_maxNPixelSharedHits.value()](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.value()](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): "
355 << m_minNSctHitsPhysical );
356
357 trackCuts["SctHits"].push_back([minNSctHitsPhysical = m_minNSctHitsPhysical.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
358 return getSummary(helper, msgHelper, xAOD::numberOfSCTHits) >= minNSctHitsPhysical;
359 });
360 }
361 if (maxIntIsSet(m_maxNSctHoles)) {
362 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT holes: " << m_maxNSctHoles );
363 trackCuts["SctHits"].push_back([maxNSctHoles = m_maxNSctHoles.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
364 return getSummary(helper, msgHelper, xAOD::numberOfSCTHoles) <= maxNSctHoles;
365 });
366 }
367 if (maxIntIsSet(m_maxNSctSharedHits)) {
368 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT shared hits: " << m_maxNSctSharedHits );
369 trackCuts["SctHits"].push_back([maxNSctSharedHits = m_maxNSctSharedHits.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
370 return getSummary(helper, msgHelper, xAOD::numberOfSCTSharedHits) <= maxNSctSharedHits;
371 });
372 }
373 if (maxIntIsSet(m_maxNSctDoubleHoles)) {
374 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum SCT double holes: " << m_maxNSctDoubleHoles );
375 trackCuts["SctHits"].push_back([maxNSctDoubleHoles = m_maxNSctDoubleHoles.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
376 return getSummary(helper, msgHelper, xAOD::numberOfSCTDoubleHoles) <= maxNSctDoubleHoles ;
377 });
378 }
379 if (m_minNSiHits > 0) {
380 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum silicon (pixel + SCT) hits: " << m_minNSiHits );
381 trackCuts["SiHits"].push_back([minNSiHits = m_minNSiHits.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
382 return getSummarySum<4,Trk_Helper>(helper, msgHelper, {xAOD::numberOfPixelHits,
383 xAOD::numberOfSCTHits,
384 xAOD::numberOfPixelDeadSensors,
385 xAOD::numberOfSCTDeadSensors} ) >= minNSiHits ;
386 });
387 }
388 if (m_minNSiHitsPhysical > 0) {
389 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum physical silicon hits (i.e. dead sensors do not count): "
390 << m_minNSiHitsPhysical );
391 trackCuts["SiHits"].push_back([minNSiHitsPhysical = m_minNSiHitsPhysical.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
392 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits, xAOD::numberOfSCTHits} ) >= minNSiHitsPhysical ;
393 });
394 }
395 if (maxIntIsSet(m_maxNSiHoles)) {
396 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum silicon holes: " << m_maxNSiHoles );
397 trackCuts["SiHits"].push_back([maxNSiHoles = m_maxNSiHoles.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
398 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHoles, xAOD::numberOfSCTHoles} ) <= maxNSiHoles ;
399 });
400 }
401 if (maxIntIsSet(m_maxNSiSharedHits)) {
402 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum silicon shared hits: " << m_maxNSiSharedHits );
403 trackCuts["SiHits"].push_back([maxNSiSharedHits = m_maxNSiSharedHits.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
404 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelSharedHits, xAOD::numberOfSCTSharedHits} ) <= maxNSiSharedHits ;
405 });
406 }
407 if (m_maxOneSharedModule) {
408 if constexpr(VERBOSE>0) ATH_MSG_INFO( " No more than one shared module:" );
409 if constexpr(VERBOSE>0) ATH_MSG_INFO( " i.e. max 1 shared pixel hit or" );
410 if constexpr(VERBOSE>0) ATH_MSG_INFO( " 2 shared SCT hits, and not both." );
411 trackCuts["SiHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
412 return getSummary(helper, msgHelper,xAOD::numberOfPixelSharedHits )
413 + getSummary(helper, msgHelper,xAOD::numberOfSCTSharedHits )/2 <= 1 ;
414 });
415 }
416 if (m_minNSiHitsIfSiSharedHits > 0) {
417 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum silicon hits if the track has shared hits: "
418 << m_minNSiHitsIfSiSharedHits );
419 trackCuts["SiHits"].push_back([minNSiHitsIfSiSharedHits = m_minNSiHitsIfSiSharedHits.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
420 return getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelSharedHits, xAOD::numberOfSCTSharedHits} ) == 0
424 xAOD::numberOfSCTDeadSensors}) >=minNSiHitsIfSiSharedHits;
425 });
426 }
427 if (maxDoubleIsSet(m_minEtaForStrictNSiHitsCut)
428 && m_minNSiHitsAboveEtaCutoff > 0) {
429 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Require " << m_minNSiHitsAboveEtaCutoff
430 << " silicon hits above eta = " << m_minEtaForStrictNSiHitsCut );
431 trackCuts["SiHits"].push_back([minEtaForStrictNSiHitsCut = m_minEtaForStrictNSiHitsCut.value(),
432 minNSiHitsAboveEtaCutoff = m_minNSiHitsAboveEtaCutoff.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
433 return std::abs(helper.eta(msgHelper)) <= minEtaForStrictNSiHitsCut
434 || getSummarySum<4,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits,
435 xAOD::numberOfSCTHits,
436 xAOD::numberOfPixelDeadSensors,
437 xAOD::numberOfSCTDeadSensors}) >= minNSiHitsAboveEtaCutoff;
438 });
439 }
440 if (m_useExperimentalInnermostLayersCut) {
441 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." );
442 trackCuts["PixHits"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
443 uint8_t pixel_holes = getSummary(helper, msgHelper,xAOD::numberOfPixelHoles);
444 return pixel_holes == 0 || ( pixel_holes<=1 && getSummary(helper, msgHelper,xAOD::numberOfInnermostPixelLayerHits) >= 1
446 && getSummary(helper, msgHelper,xAOD::numberOfNextToInnermostPixelLayerHits) == 0 );
447 });
448 }
449#ifndef XAOD_ANALYSIS
450 if (m_minNSiHitsMod > 0) {
451 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits (2*pix + sct) (does not include dead sensors)= "
452 << m_minNSiHitsMod );
453 trackCuts["SiHits"].push_back([minNSiHitsMod = m_minNSiHitsMod.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
454 return getSummarySum<3,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits,
455 xAOD::numberOfPixelHits, // pixel hits count twice in this definition
456 xAOD::numberOfSCTHits}) >= minNSiHitsMod;
457 });
458 }
459 if (m_minNSiHitsModTop > 0 || m_minNSiHitsModBottom > 0) {
460 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits in top half = "
461 << m_minNSiHitsModTop );
462 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum modified Si hits in bottom half = "
463 << m_minNSiHitsModBottom );
464 trackCuts["SiHits"].push_back([minNSiHitsModTop = m_minNSiHitsModTop.value(),
465 minNSiHitsModBottom = m_minNSiHitsModBottom](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
466 auto [top,bottom] = getSiHitsTopBottom(helper, msgHelper);
467 return top >= minNSiHitsModTop && bottom >= minNSiHitsModBottom;
468 });
469 }
470#endif
471 if (m_maxEtaForTrtHitCuts > 0. && m_maxTrtEtaAcceptance < m_maxEtaForTrtHitCuts) {
472 if constexpr(VERBOSE>0) ATH_MSG_INFO( " -- TRT hit cuts applied above eta = " << m_maxTrtEtaAcceptance
473 << " and below eta = " << m_maxEtaForTrtHitCuts << " --" );
474 if (m_minNTrtHits > 0) {
475 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance: " << m_minNTrtHits );
476 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,1>( m_maxTrtEtaAcceptance, m_maxEtaForTrtHitCuts, m_minNTrtHits,
478 }
479 if (m_minNTrtHitsPlusOutliers > 0) {
480 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance including outliers: " << m_minNTrtHitsPlusOutliers );
481 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,2>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHitsPlusOutliers,
483 }
484 if (m_minNTrtHighThresholdHits > 0) {
485 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance above high energy threshold: "
486 << m_minNTrtHighThresholdHits );
487 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,1>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHighThresholdHits,
489 }
490 if (m_minNTrtHighThresholdHitsPlusOutliers > 0) {
491 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum TRT hits outside eta acceptance above high energy threshold including outliers: "
492 << m_minNTrtHighThresholdHitsPlusOutliers );
493 trackCuts["TrtHits"].push_back( MinTRTHitsCut<Trk_Helper,2>( m_maxTrtEtaAcceptance,m_maxEtaForTrtHitCuts, m_minNTrtHighThresholdHitsPlusOutliers,
495 }
496 if (maxDoubleIsSet(m_maxTrtHighEFraction)) { // I think this condition could be instead that it is between 0 and 1
497 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum ratio of high threshold to regular TRT hits outside eta acceptance: "
498 << m_maxTrtHighEFraction);
499 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance.value(),
500 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts.value(),
501 maxTrtHighEFraction = m_maxTrtHighEFraction.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
502 double absEta = std::abs( helper.eta( msgHelper) );
503 return (absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
504 || getSummary(helper, msgHelper,xAOD::numberOfTRTHighThresholdHits )
505 <= maxTrtHighEFraction * getSummary(helper, msgHelper,xAOD::numberOfTRTHits );
506 });
507 }
508 if (maxDoubleIsSet(m_maxTrtHighEFractionWithOutliers)) {
509 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum ratio of high threshold to regular TRT hits above eta acceptance including outliers: "
510 << m_maxTrtHighEFractionWithOutliers);
511 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance.value(),
512 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts.value(),
513 maxTrtHighEFractionWithOutliers = m_maxTrtHighEFractionWithOutliers.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
514 double absEta = std::abs( helper.eta( msgHelper) );
515 return (absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
516 || ( getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfTRTHighThresholdHits, xAOD::numberOfTRTHighThresholdOutliers} ))
517 <= maxTrtHighEFractionWithOutliers * ( getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfTRTHits, xAOD::numberOfTRTOutliers} ));
518 });
519 }
520 if (m_maxTrtOutlierFraction < 1. && m_maxTrtOutlierFraction >= 0.) {
521 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum fraction of TRT hits that are outliers: " << m_maxTrtOutlierFraction );
522 trackCuts["TrtHits"].push_back([maxTrtEtaAcceptance = m_maxTrtEtaAcceptance.value(),
523 maxEtaForTrtHitCuts = m_maxEtaForTrtHitCuts.value(),
524 maxTrtOutlierFraction = m_maxTrtOutlierFraction.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
525 double absEta = std::abs( helper.eta( msgHelper) );
526 uint8_t trt_outliers = getSummary(helper, msgHelper,xAOD::numberOfTRTOutliers );
527 return ( absEta <= maxTrtEtaAcceptance || absEta > maxEtaForTrtHitCuts)
528 || trt_outliers <= maxTrtOutlierFraction * ( trt_outliers + getSummary(helper, msgHelper,xAOD::numberOfTRTHits) );
529 });
530 }
531 }
532
533 // fit quality cuts
534 if (m_useEtaDependentMaxChiSq) {
535 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Using pre-defined eta-dependent maximum chi squared (no longer recommended)." );
536 trackCuts["FitQuality"].push_back([](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
537 double eta = helper.eta(msgHelper);
538 double fit_chi_square = getFitChiSquare(helper,msgHelper);
539 double fit_ndof = getFitNDoF(helper,msgHelper);
540 if (std::abs( eta) < 1.9) {
541 return fit_chi_square <= fit_ndof * ( 4.4 + 0.32*sqr(eta) );
542 }
543 else {
544 return fit_chi_square <= fit_ndof * ( 26.9 - 19.6978*std::abs(eta) + 4.4534*sqr(eta) );
545 }
546 });
547 }
548 if (maxDoubleIsSet(m_maxChiSq)) {
549 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum chi squared: " << m_maxChiSq );
550 trackCuts["FitQuality"].push_back([maxChiSq = m_maxChiSq.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
551 return getFitChiSquare(helper,msgHelper) <= maxChiSq;
552 });
553 }
554 if (maxDoubleIsSet(m_maxChiSqperNdf)) {
555 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Maximum chi squared per degree of freedom: " << m_maxChiSqperNdf );
556 trackCuts["FitQuality"].push_back([maxChiSqperNdf = m_maxChiSqperNdf.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
557 return getFitChiSquare(helper,msgHelper) <= maxChiSqperNdf * getFitNDoF(helper,msgHelper);
558 });
559 }
560 if (m_minProb > 0.) {
561 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum chi squared probability: " << m_minProb );
562 trackCuts["FitQuality"].push_back([minProb = m_minProb.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
563 return TMath::Prob( getFitChiSquare(helper,msgHelper),getFitNDoF(helper,msgHelper)) >= minProb;
564 });
565 }
566 if (maxDoubleIsSet(m_minPtForProbCut) && m_minProbAbovePtCutoff > 0.) {
567 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum chi-sq probability of " << m_minProbAbovePtCutoff
568 << " above pt of " << m_minPtForProbCut*1e-3 << " GeV." );
569 trackCuts["FitQuality"].push_back([minPtForProbCut = m_minPtForProbCut.value(),
570 minProbAbovePtCutoff = m_minProbAbovePtCutoff.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
571 return helper.pt(msgHelper) <= minPtForProbCut
572 || TMath::Prob( getFitChiSquare(helper,msgHelper),getFitNDoF(helper,msgHelper)) >= minProbAbovePtCutoff;
573 });
574 }
575
576 // dE/dx cuts
577 if (m_minNUsedHitsdEdx > 0) {
578 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum used hits for dEdx: " << m_minNUsedHitsdEdx );
579 trackCuts["dEdxHits"].push_back([minNUsedHitsdEdx = m_minNUsedHitsdEdx.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
580 return getNumberOfUsedHitsdEdx(helper,msgHelper) >= minNUsedHitsdEdx;
581 });
582 }
583 if (m_minNOverflowHitsdEdx > 0) {
584 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum IBL overflow hits for dEdx: " << m_minNOverflowHitsdEdx );
585 trackCuts["dEdxHits"].push_back([minNOverflowHitsdEdx = m_minNOverflowHitsdEdx.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
586 return getNumberOfIBLOverflowsdEdx(helper,msgHelper) >= minNOverflowHitsdEdx;
587 });
588 }
589 if (m_minEProbabilityHT > 0) {
590 if constexpr(VERBOSE>0) ATH_MSG_INFO( " Minimum high threshold electron probability: " << m_minEProbabilityHT );
591 if (m_eProbHTonlyForXe) {
592 if constexpr(VERBOSE>0) ATH_MSG_INFO( " (only applied on tracks where all TRT hits are Xenon)" );
593 trackCuts["eProbHT"].push_back([minEProbabilityHT = m_minEProbabilityHT.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
594 return getSummarySum<2,Trk_Helper>(helper, msgHelper, {xAOD::numberOfTRTHits, xAOD::numberOfTRTOutliers})
595 > getSummary(helper, msgHelper, xAOD::numberOfTRTXenonHits)
596 || getEProbabilityHT(helper,msgHelper) >= minEProbabilityHT;
597 });
598 } else {
599 trackCuts["eProbHT"].push_back([minEProbabilityHT = m_minEProbabilityHT.value()](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
600 return getEProbabilityHT(helper,msgHelper) >= minEProbabilityHT;
601 });
602 }
603 }
604
605 if (!m_vecEtaCutoffsForSiHitsCut.empty() || !m_vecMinNSiHitsAboveEta.empty()) {
606 auto cutSize = m_vecEtaCutoffsForSiHitsCut.size();
607 if (cutSize != m_vecMinNSiHitsAboveEta.size()) {
608 ATH_MSG_ERROR( "Eta cutoffs and Silicon hit cuts must be vectors of the same length." );
609 return StatusCode::FAILURE;
610 }
611 if constexpr(VERBOSE>0) {
612 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
613 ATH_MSG_INFO( " for " << m_vecEtaCutoffsForSiHitsCut[i_cut]
614 << " < eta < " << m_vecEtaCutoffsForSiHitsCut[i_cut+1]
615 << " ,Silicon hits >= " << m_vecMinNSiHitsAboveEta[i_cut] );
616 }
617 }
618 if (!checkOrder(m_vecEtaCutoffsForSiHitsCut.value())) {
619 ATH_MSG_ERROR( "Eta values not in ascending order." );
620 return StatusCode::FAILURE;
621 }
622 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for eta > " << m_vecEtaCutoffsForSiHitsCut[cutSize-1]
623 << " ,Silicon hits >= " << m_vecMinNSiHitsAboveEta[cutSize-1] );
624
625 trackCuts["SiHits"].push_back([p_vecEtaCutoffsForSiHitsCut = &std::as_const(m_vecEtaCutoffsForSiHitsCut.value()),
626 p_vecMinNSiHitsAboveEta = &std::as_const(m_vecMinNSiHitsAboveEta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
627 double abs_eta = std::abs(helper.eta(msgHelper));
628 unsigned int bin_i = findBin(*p_vecEtaCutoffsForSiHitsCut, abs_eta);
629 return bin_i >= p_vecMinNSiHitsAboveEta->size()
630 || abs_eta>5.0
631 || getSummarySum<4,Trk_Helper>(helper, msgHelper,{xAOD::numberOfPixelHits,
632 xAOD::numberOfSCTHits,
633 xAOD::numberOfPixelDeadSensors,
634 xAOD::numberOfSCTDeadSensors}) >= (*p_vecMinNSiHitsAboveEta)[bin_i];
635 });
636 }
637
638 if (!m_vecEtaCutoffsForPtCut.empty() || !m_vecMinPtAboveEta.empty()) {
639 auto cutSize = m_vecEtaCutoffsForPtCut.size();
640 if (cutSize != m_vecMinPtAboveEta.size()) {
641 ATH_MSG_ERROR( "Eta cutoffs and pT cuts must be vectors of the same length." );
642 return StatusCode::FAILURE;
643 }
644 if constexpr(VERBOSE>0) {
645 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
646 ATH_MSG_INFO( " for " << m_vecEtaCutoffsForPtCut[i_cut]
647 << " < eta < " << m_vecEtaCutoffsForPtCut[i_cut+1]
648 << " ,transverse momentum >= " << m_vecMinPtAboveEta[i_cut] );
649 }
650 }
651 if (!checkOrder(m_vecEtaCutoffsForPtCut.value())) {
652 ATH_MSG_ERROR( "Eta values not in ascending order." );
653 return StatusCode::FAILURE;
654 }
655 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for eta > " << m_vecEtaCutoffsForPtCut[cutSize-1]
656 << " ,transverse momentum >= " << m_vecMinPtAboveEta[cutSize-1] );
657 trackCuts["Pt"].push_back([p_vecEtaCutoffsForPtCut = &std::as_const(m_vecEtaCutoffsForPtCut.value()),
658 p_vecMinPtAboveEta = &std::as_const(m_vecMinPtAboveEta.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
659 double abs_eta = std::abs(helper.eta(msgHelper));
660 unsigned int bin_i = findBin(*p_vecEtaCutoffsForPtCut, abs_eta);
661 return bin_i >= p_vecMinPtAboveEta->size() || abs_eta > 5.0 || helper.pt(msgHelper) >= (*p_vecMinPtAboveEta)[bin_i];
662 });
663 }
664
665 if (!m_vecPtCutoffsForSctHitsCut.empty() || !m_vecMinNSctHitsAbovePt.empty()) {
666 auto cutSize = m_vecPtCutoffsForSctHitsCut.size();
667 if (cutSize != m_vecMinNSctHitsAbovePt.size()) {
668 ATH_MSG_ERROR( "Pt cutoffs and SCT hit cuts must be vectors of the same length." );
669 return StatusCode::FAILURE;
670 }
671 if constexpr(VERBOSE>0) {
672 for (size_t i_cut=0; i_cut<cutSize-1; ++i_cut) {
673 ATH_MSG_INFO( " for " << m_vecPtCutoffsForSctHitsCut[i_cut]
674 << " < pt < " << m_vecPtCutoffsForSctHitsCut[i_cut+1]
675 << " MeV,\tSCT hits >= " << m_vecMinNSctHitsAbovePt[i_cut] );
676 }
677 }
678 if (!checkOrder(m_vecPtCutoffsForSctHitsCut.value())) {
679 ATH_MSG_ERROR( "Pt values not in ascending order." );
680 return StatusCode::FAILURE;
681 }
682 if constexpr(VERBOSE>0) ATH_MSG_INFO( " for pt > " << m_vecPtCutoffsForSctHitsCut[cutSize-1]
683 << " MeV,\t\tSCT hits >= " << m_vecMinNSctHitsAbovePt[cutSize-1] );
684 trackCuts["SctHits"].push_back([p_vecPtCutoffsForSctHitsCut = &std::as_const(m_vecPtCutoffsForSctHitsCut.value()),
685 p_vecMinNSctHitsAbovePt = &std::as_const(m_vecMinNSctHitsAbovePt.value())](Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
686 double pt = helper.pt(msgHelper);
687 unsigned int bin_i = findBin(*p_vecPtCutoffsForSctHitsCut, pt);
688 return bin_i >= p_vecPtCutoffsForSctHitsCut->size()
689 || getSummarySum<2,Trk_Helper>(helper, msgHelper,{xAOD::numberOfSCTHits,
690 xAOD::numberOfSCTDeadSensors}) >= (*p_vecMinNSctHitsAbovePt)[bin_i];
691 });
692 }
693
694 if (!m_vecPtCutoffsForZ0SinThetaCut.empty() ||
695 !m_vecEtaCutoffsForZ0SinThetaCut.empty() ||
696 !m_vecvecMaxZ0SinThetaAboveEtaPt.empty()) {
697 auto etaSize = m_vecEtaCutoffsForZ0SinThetaCut.size();
698 auto ptSize = m_vecPtCutoffsForZ0SinThetaCut.size();
699 if (etaSize != m_vecvecMaxZ0SinThetaAboveEtaPt.size()) {
700 ATH_MSG_ERROR( "Eta cutoffs and Z0SinTheta cuts must be vectors of the same length." );
701 return StatusCode::FAILURE;
702 }
703 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
704 if (ptSize != m_vecvecMaxZ0SinThetaAboveEtaPt[i_size].size()) {
705 ATH_MSG_ERROR( "Pt cutoffs and Z0SinTheta cuts must be vectors of the same length." );
706 return StatusCode::FAILURE;
707 }
708 }
709
710 std::stringstream pTRangeBuffer;
711 std::copy(m_vecPtCutoffsForZ0SinThetaCut.begin(), m_vecPtCutoffsForZ0SinThetaCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
712 std::string pTString=pTRangeBuffer.str();
713 if constexpr(VERBOSE>0) ATH_MSG_INFO("Z0SinTheta cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
714 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
715 {
716 std::stringstream etaRangeBuffer;
717 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForZ0SinThetaCut[i_cut_eta] << " < |#eta| < ";
718 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForZ0SinThetaCut[i_cut_eta+1];
719 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
720
721 std::stringstream cutBuffer;
722 std::copy(m_vecvecMaxZ0SinThetaAboveEtaPt[i_cut_eta].begin(), m_vecvecMaxZ0SinThetaAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
723 std::string cutString=cutBuffer.str();
724
725 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
726 }
727
728 if (!checkOrder(m_vecEtaCutoffsForZ0SinThetaCut.value())) {
729 ATH_MSG_ERROR( "Eta values not in ascending order." );
730 return StatusCode::FAILURE;
731 }
732 if (!checkOrder(m_vecPtCutoffsForZ0SinThetaCut.value())) {
733 ATH_MSG_ERROR( "Pt values not in ascending order." );
734 return StatusCode::FAILURE;
735 }
736
737 trackCuts["Z0SinTheta"].push_back([p_vecEtaCutoffsForZ0SinThetaCut = &std::as_const(m_vecEtaCutoffsForZ0SinThetaCut.value()),
738 p_vecPtCutoffsForZ0SinThetaCut = &std::as_const(m_vecPtCutoffsForZ0SinThetaCut.value()),
739 p_vecvecMaxZ0SinThetaAboveEtaPt = &std::as_const(m_vecvecMaxZ0SinThetaAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
740 double eta = helper.eta(msgHelper);
741 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForZ0SinThetaCut, std::fabs(eta));
742 double pt = helper.pt(msgHelper);
743 unsigned int bin_pt = findBin(*p_vecPtCutoffsForZ0SinThetaCut, pt);
744 return bin_eta >= p_vecEtaCutoffsForZ0SinThetaCut->size()
745 || bin_pt >= p_vecPtCutoffsForZ0SinThetaCut->size()
746 || std::fabs(helper.z0(msgHelper) * std::sin(helper.theta(msgHelper))) <= (*p_vecvecMaxZ0SinThetaAboveEtaPt)[bin_eta][bin_pt];
747 });
748 }
749
750 if (!m_vecPtCutoffsForD0Cut.empty() ||
751 !m_vecEtaCutoffsForD0Cut.empty() ||
752 !m_vecvecMaxD0AboveEtaPt.empty()) {
753 auto etaSize = m_vecEtaCutoffsForD0Cut.size();
754 auto ptSize = m_vecPtCutoffsForD0Cut.size();
755 if (etaSize != m_vecvecMaxD0AboveEtaPt.size()) {
756 ATH_MSG_ERROR( "Eta cutoffs and D0 cuts must be vectors of the same length." );
757 return StatusCode::FAILURE;
758 }
759 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
760 if (ptSize != m_vecvecMaxD0AboveEtaPt[i_size].size()) {
761 ATH_MSG_ERROR( "Pt cutoffs and D0 cuts must be vectors of the same length." );
762 return StatusCode::FAILURE;
763 }
764 }
765
766 std::stringstream pTRangeBuffer;
767 std::copy(m_vecPtCutoffsForD0Cut.begin(), m_vecPtCutoffsForD0Cut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
768 std::string pTString=pTRangeBuffer.str();
769 if constexpr(VERBOSE>0) ATH_MSG_INFO("D0 cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
770 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
771 {
772 std::stringstream etaRangeBuffer;
773 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForD0Cut[i_cut_eta] << " < |#eta| < ";
774 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForD0Cut[i_cut_eta+1];
775 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
776
777 std::stringstream cutBuffer;
778 std::copy(m_vecvecMaxD0AboveEtaPt[i_cut_eta].begin(), m_vecvecMaxD0AboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
779 std::string cutString=cutBuffer.str();
780
781 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
782 }
783
784 if (!checkOrder(m_vecEtaCutoffsForD0Cut.value())) {
785 ATH_MSG_ERROR( "Eta values not in ascending order." );
786 return StatusCode::FAILURE;
787 }
788 if (!checkOrder(m_vecPtCutoffsForD0Cut.value())) {
789 ATH_MSG_ERROR( "Pt values not in ascending order." );
790 return StatusCode::FAILURE;
791 }
792
793 trackCuts["D0"].push_back([p_vecEtaCutoffsForD0Cut = &std::as_const(m_vecEtaCutoffsForD0Cut.value()),
794 p_vecPtCutoffsForD0Cut = &std::as_const(m_vecPtCutoffsForD0Cut.value()),
795 p_vecvecMaxD0AboveEtaPt = &std::as_const(m_vecvecMaxD0AboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
796 double eta = helper.eta(msgHelper);
797 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForD0Cut, std::fabs(eta));
798 double pt = helper.pt(msgHelper);
799 unsigned int bin_pt = findBin(*p_vecPtCutoffsForD0Cut, pt);
800 return bin_eta >= p_vecEtaCutoffsForD0Cut->size()
801 || bin_pt >= p_vecPtCutoffsForD0Cut->size()
802 || std::fabs(helper.d0(msgHelper)) <= (*p_vecvecMaxD0AboveEtaPt)[bin_eta][bin_pt];
803 });
804 }
805
806 if (!m_vecPtCutoffsForSctHolesCut.empty() ||
807 !m_vecEtaCutoffsForSctHolesCut.empty() ||
808 !m_vecvecMaxSctHolesAboveEtaPt.empty()) {
809 auto etaSize = m_vecEtaCutoffsForSctHolesCut.size();
810 auto ptSize = m_vecPtCutoffsForSctHolesCut.size();
811 if (etaSize != m_vecvecMaxSctHolesAboveEtaPt.size()) {
812 ATH_MSG_ERROR( "Eta cutoffs and SctHoles cuts must be vectors of the same length." );
813 return StatusCode::FAILURE;
814 }
815 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
816 if (ptSize != m_vecvecMaxSctHolesAboveEtaPt[i_size].size()) {
817 ATH_MSG_ERROR( "Pt cutoffs and SctHoles cuts must be vectors of the same length." );
818 return StatusCode::FAILURE;
819 }
820 }
821
822 std::stringstream pTRangeBuffer;
823 std::copy(m_vecPtCutoffsForSctHolesCut.begin(), m_vecPtCutoffsForSctHolesCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
824 std::string pTString=pTRangeBuffer.str();
825 if constexpr(VERBOSE>0) ATH_MSG_INFO("SctHoles cuts (<=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
826 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
827 {
828 std::stringstream etaRangeBuffer;
829 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHolesCut[i_cut_eta] << " < |#eta| < ";
830 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHolesCut[i_cut_eta+1];
831 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
832
833 std::stringstream cutBuffer;
834 std::copy(m_vecvecMaxSctHolesAboveEtaPt[i_cut_eta].begin(), m_vecvecMaxSctHolesAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
835 std::string cutString=cutBuffer.str();
836
837 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
838 }
839
840 if (!checkOrder(m_vecEtaCutoffsForSctHolesCut.value())) {
841 ATH_MSG_ERROR( "Eta values not in ascending order." );
842 return StatusCode::FAILURE;
843 }
844 if (!checkOrder(m_vecPtCutoffsForSctHolesCut.value())) {
845 ATH_MSG_ERROR( "Pt values not in ascending order." );
846 return StatusCode::FAILURE;
847 }
848
849 trackCuts["SctHits"].push_back([p_vecEtaCutoffsForSctHolesCut = &std::as_const(m_vecEtaCutoffsForSctHolesCut.value()),
850 p_vecPtCutoffsForSctHolesCut = &std::as_const(m_vecPtCutoffsForSctHolesCut.value()),
851 p_vecvecMaxSctHolesAboveEtaPt = &std::as_const(m_vecvecMaxSctHolesAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
852 double eta = helper.eta(msgHelper);
853 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForSctHolesCut, std::fabs(eta));
854 double pt = helper.pt(msgHelper);
855 unsigned int bin_pt = findBin(*p_vecPtCutoffsForSctHolesCut, pt);
856 return bin_eta >= p_vecEtaCutoffsForSctHolesCut->size()
857 || bin_pt >= p_vecPtCutoffsForSctHolesCut->size()
858 || getSummary(helper, msgHelper, xAOD::numberOfSCTHoles) <= (*p_vecvecMaxSctHolesAboveEtaPt)[bin_eta][bin_pt];
859 });
860 }
861
862 if (!m_vecPtCutoffsForSctHitsPlusDeadCut.empty() ||
863 !m_vecEtaCutoffsForSctHitsPlusDeadCut.empty() ||
864 !m_vecvecMinSctHitsPlusDeadAboveEtaPt.empty()) {
865 auto etaSize = m_vecEtaCutoffsForSctHitsPlusDeadCut.size();
866 auto ptSize = m_vecPtCutoffsForSctHitsPlusDeadCut.size();
867 if (etaSize != m_vecvecMinSctHitsPlusDeadAboveEtaPt.size()) {
868 ATH_MSG_ERROR( "Eta cutoffs and SctHitsPlusDead cuts must be vectors of the same length." );
869 return StatusCode::FAILURE;
870 }
871 for (size_t i_size=0; i_size<etaSize-1; ++i_size) {
872 if (ptSize != m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_size].size()) {
873 ATH_MSG_ERROR( "Pt cutoffs and SctHitsPlusDead cuts must be vectors of the same length." );
874 return StatusCode::FAILURE;
875 }
876 }
877
878 std::stringstream pTRangeBuffer;
879 std::copy(m_vecPtCutoffsForSctHitsPlusDeadCut.begin(), m_vecPtCutoffsForSctHitsPlusDeadCut.end(), std::ostream_iterator<double>(pTRangeBuffer, ", "));
880 std::string pTString=pTRangeBuffer.str();
881 if constexpr(VERBOSE>0) ATH_MSG_INFO("SctHitsPlusDead cuts (>=) for pT above "<<pTString.substr(0, pTString.size()-2)<<"MeV, respectively:");
882 for (size_t i_cut_eta=0; i_cut_eta<etaSize; ++i_cut_eta)
883 {
884 std::stringstream etaRangeBuffer;
885 etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHitsPlusDeadCut[i_cut_eta] << " < |#eta| < ";
886 if(i_cut_eta!=etaSize-1) etaRangeBuffer << std::setprecision(2) << std::fixed << m_vecEtaCutoffsForSctHitsPlusDeadCut[i_cut_eta+1];
887 else etaRangeBuffer << std::setprecision(2) << std::fixed <<m_maxAbsEta;
888
889 std::stringstream cutBuffer;
890 std::copy(m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_cut_eta].begin(), m_vecvecMinSctHitsPlusDeadAboveEtaPt[i_cut_eta].end(), std::ostream_iterator<double>(cutBuffer, ", "));
891 std::string cutString=cutBuffer.str();
892
893 if constexpr(VERBOSE>0) ATH_MSG_INFO(" for "<<etaRangeBuffer.str()<<": "<<cutString.substr(0, cutString.size()-2));
894 }
895
896 if (!checkOrder(m_vecEtaCutoffsForSctHitsPlusDeadCut.value())) {
897 ATH_MSG_ERROR( "Eta values not in ascending order." );
898 return StatusCode::FAILURE;
899 }
900 if (!checkOrder(m_vecPtCutoffsForSctHitsPlusDeadCut.value())) {
901 ATH_MSG_ERROR( "Pt values not in ascending order." );
902 return StatusCode::FAILURE;
903 }
904
905 trackCuts["SctHits"].push_back([p_vecEtaCutoffsForSctHitsPlusDeadCut = &std::as_const(m_vecEtaCutoffsForSctHitsPlusDeadCut.value()),
906 p_vecPtCutoffsForSctHitsPlusDeadCut = &std::as_const(m_vecPtCutoffsForSctHitsPlusDeadCut.value()),
907 p_vecvecMinSctHitsPlusDeadAboveEtaPt = &std::as_const(m_vecvecMinSctHitsPlusDeadAboveEtaPt.value())] (Trk_Helper helper, const asg::AsgMessaging &msgHelper) {
908 double eta = helper.eta(msgHelper);
909 unsigned int bin_eta = findBin(*p_vecEtaCutoffsForSctHitsPlusDeadCut, std::fabs(eta));
910 double pt = helper.pt(msgHelper);
911 unsigned int bin_pt = findBin(*p_vecPtCutoffsForSctHitsPlusDeadCut, pt);
912 return bin_eta >= p_vecEtaCutoffsForSctHitsPlusDeadCut->size()
913 || bin_pt >= p_vecPtCutoffsForSctHitsPlusDeadCut->size()
914 || getSummarySum<2,Trk_Helper>(helper, msgHelper, {xAOD::numberOfSCTHits, xAOD::numberOfSCTDeadSensors}) >= (*p_vecvecMinSctHitsPlusDeadAboveEtaPt)[bin_eta][bin_pt];
915 });
916 }
917
918 return StatusCode::SUCCESS;
919}
920
921
922template <class Trk_Helper>
924 const std::map< std::string, std::vector< std::function<bool(Trk_Helper helper, const asg::AsgMessaging &msgHelper)> > > &trackCuts) const {
925 if (!m_isInitialized) {
926 if (!m_warnInit) {
927 ATH_MSG_WARNING( "Tool is not initialized! Calling accept() will not be very helpful." );
928 m_warnInit = true;
929 }
930 }
931
932 asg::AcceptData acceptData(&m_acceptInfo);
933 bool passAll = true;
934
935 // loop over all cuts
936 UShort_t cutFamilyIndex = 0;
937 for ( const auto& cutFamily : trackCuts ) {
938 bool pass = true;
939
940 for ( const auto& cut : cutFamily.second ) {
941 if (! cut(helper, *m_msgHelper) ) {
942 pass = false;
943 break;
944 }
945 }
946
947 // @TODO really always run through all cuts even if passed is false ?
948 passAll &= pass;
949 acceptData.setCutResult( cutFamilyIndex, pass );
950 cutFamilyIndex++;
951 }
952
953 {
954 // lock access to m_numTracksPassedCuts
955 std::lock_guard<std::mutex> lock(m_mutex);
956 for (unsigned int idx=0; idx < trackCuts.size(); ++idx) {
957 assert(idx<m_numTracksPassedCuts.size());
958 m_numTracksPassedCuts[idx] += acceptData.getCutResult(idx);
959 }
960 }
961 if (passAll) m_numTracksPassed++;
963
964 return acceptData;
965
966}
967
968
970{
971 if (!m_isInitialized) {
972 ATH_MSG_ERROR( "You are attempting to finalize a tool that has not been initialized()." );
973 }
974
975#ifdef XAOD_ANALYSIS
976 if (m_numTracksProcessed == 0) {
977 ATH_MSG_INFO( "No tracks processed in selection tool." );
978 return StatusCode::SUCCESS;
979 }
980
981 // Only printed out for analysis
983 << m_numTracksPassed*100./m_numTracksProcessed << "% passed all cuts." );
984 for (const auto& cutFamily : m_trackParticleCuts) {
985 // lock(m_mutex) is not needed because this is inside of non-const finalize method.
986 uint64_t numPassed = m_numTracksPassedCuts.at(m_acceptInfo.getCutPosition(cutFamily.first));
987 ATH_MSG_INFO( numPassed << " = " << numPassed*100./m_numTracksProcessed << "% passed "
988 << cutFamily.first << " cut." );
989 }
990#endif
991
992 return StatusCode::SUCCESS;
993}
994
995
1004
1005
1018{
1019
1020 asg::AcceptData acceptData(&m_acceptInfo);
1021 // Check if this is a track:
1022 if( p->type() != xAOD::Type::TrackParticle ) {
1023 ATH_MSG_ERROR( "accept(...) Function received a non-track" );
1024 return acceptData;
1025 }
1026
1027 // Cast it to a track (we have already checked its type so we do not have to dynamic_cast):
1028 const xAOD::TrackParticle* trk = static_cast< const xAOD::TrackParticle* >( p );
1029
1030 // Let the specific function do the work:
1031 return accept( *trk, nullptr );
1032}
1033
1034
1061 const xAOD::Vertex* vtx ) const
1062{
1063 asg::AcceptData acceptData(&m_acceptInfo);
1064 if (m_trackParticleCuts.empty()) {
1067 return acceptData;
1068 }
1069
1070 InDetAccessor::TrackParticleHelper track_helper(trk,vtx);
1071 return accept( track_helper, m_trackParticleCuts);
1072}
1073
1074#ifndef XAOD_ANALYSIS
1084 const Trk::Vertex* vertex ) const
1085{
1086 if (!m_isInitialized) ATH_MSG_WARNING( "Tool is not initialized! Calling accept() will not be very helpful." );
1087
1088 asg::AcceptData acceptData(&m_acceptInfo);
1089 if (m_trkTrackCuts.empty()) {
1092 return acceptData;
1093 }
1094
1095 const Trk::TrackParameters* perigee = track.perigeeParameters();
1096
1097 if ( perigee == nullptr || !perigee->covariance() ) {
1098 ATH_MSG_WARNING( "Track preselection: Zero pointer to parameterbase* received (most likely a track without perigee). This track will not pass any cuts." );
1099 return acceptData;
1100 }
1101
1102 std::unique_ptr<const Trk::TrackParameters> paramsAtVertex;
1103 if (vertex) {
1104 Trk::PerigeeSurface perigeeSurface(vertex->position());
1105 paramsAtVertex =
1106 m_extrapolator->extrapolate(Gaudi::Hive::currentContext(),
1107 *perigee,
1108 perigeeSurface,
1110 true,
1111 track.info().particleHypothesis());
1112 perigee = paramsAtVertex.get();
1113 }
1114
1115 if ( perigee == nullptr || !perigee->covariance() ) {
1116 ATH_MSG_INFO( "Track preselection: cannot make a measured perigee. This track will not pass any cuts." );
1117 if (!m_initTrkTools)
1118 ATH_MSG_INFO( "The user should set \"UseTrkTrackTools\" to true if they want the extrapolation tool to try to get a perigee." );
1119 return acceptData;
1120 }
1121
1122
1123 std::unique_ptr<Trk::TrackSummary> cleanup_summary;
1124 const Trk::TrackSummary* summary = track.trackSummary();
1125 if (summary == nullptr && m_trackSumToolAvailable) {
1126 cleanup_summary = m_trackSumTool->summary(Gaudi::Hive::currentContext(),track);
1127 summary = cleanup_summary.get();
1128 }
1129 if (summary == nullptr) {
1130 ATH_MSG_INFO( "Track preselection: cannot get a track summary. This track will not pass any cuts." );
1131 if (!m_initTrkTools)
1132 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." );
1133 return acceptData;
1134 }
1135
1136 InDetAccessor::TrkTrackHelper track_helper(track,*summary, perigee);
1137 acceptData = accept( track_helper, m_trkTrackCuts);
1138 return acceptData;
1139}
1140
1141#endif // XAOD_ANALYSIS
1142
1158#ifdef __GNUC__
1159#pragma GCC diagnostic push
1160#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1161#endif
1162void InDet::InDetTrackSelectionTool::setCutLevel(InDet::CutLevel level, bool overwrite )
1163{
1164#ifndef XAOD_STANDALONE
1165 ATH_MSG_WARNING( "InDetTrackSelectionTool::setCutLevel() is not designed to be called manually in Athena." );
1166 ATH_MSG_WARNING( "It may not behave as intended. Instead, configure it in the job options through the CutLevel property." );
1167#endif // XAOD_STANDALONE
1168 if (!m_cutLevel.empty()) {
1169 ATH_MSG_WARNING( "Cut level already set to " << m_cutLevel << ". Calling setCutLevel() is not expected." );
1170 }
1171 setCutLevelPrivate(level, overwrite);
1172}
1173#ifdef __GNUC__
1174#pragma GCC diagnostic pop
1175#endif
1176
1177void InDet::InDetTrackSelectionTool::setCutLevelPrivate(InDet::CutLevel level, bool overwrite)
1178{
1179 switch (level) {
1180 case CutLevel::NoCut :
1181 if (m_isInitialized) {
1182 // this check is in here so that it only happens once per call to setCutLevel,
1183 // but will still warn if only the private version is called somehow.
1184 ATH_MSG_WARNING( "Trying to set cut level while the tool is already initialized." );
1185 ATH_MSG_WARNING( "This will almost certainly not exhibit intended behavior." );
1186 }
1187 if (overwrite) {
1188 // minimum cuts will default to -1, so if a user wishes to remove a cut
1189 // from a preset level they can do so by setting the minimum to zero.
1190 // maximum cuts can be removed from a preset level by setting them negative.
1191 m_minPt = -1.; // in MeV
1192 m_minP = -1.;
1209 m_minNPixelHits = -1;
1213 m_minNSctHits = -1;
1218 m_minNSiHits = -1;
1225 m_maxOneSharedModule = false;
1227 m_maxEtaForTrtHitCuts = -1.; // this is really a minimum eta above which cuts are not applied
1228 m_minNTrtHits = -1;
1236 m_minProb = -1.;
1241 m_minNUsedHitsdEdx = -1;
1243 m_minEProbabilityHT = -1.;
1244 m_eProbHTonlyForXe = false;
1245#ifndef XAOD_ANALYSIS
1246 m_minNSiHitsMod = -1;
1247 m_minNSiHitsModTop = -1;
1249#endif
1250 m_vecEtaCutoffsForSiHitsCut = std::vector<double>();
1251 m_vecMinNSiHitsAboveEta = std::vector<int>();
1252 m_vecEtaCutoffsForPtCut = std::vector<double>();
1253 m_vecMinPtAboveEta = std::vector<double>();
1254 m_vecPtCutoffsForSctHitsCut = std::vector<double>();
1255 m_vecMinNSctHitsAbovePt = std::vector<int>();
1256 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>();
1257 m_vecPtCutoffsForZ0SinThetaCut = std::vector<double>();
1258 m_vecvecMaxZ0SinThetaAboveEtaPt = std::vector<std::vector<double>>();
1259 m_vecEtaCutoffsForD0Cut = std::vector<double>();
1260 m_vecPtCutoffsForD0Cut = std::vector<double>();
1261 m_vecvecMaxD0AboveEtaPt = std::vector<std::vector<double>>();
1262 m_vecEtaCutoffsForSctHolesCut = std::vector<double>();
1263 m_vecPtCutoffsForSctHolesCut = std::vector<double>();
1264 m_vecvecMaxSctHolesAboveEtaPt = std::vector<std::vector<double>>();
1265 m_vecEtaCutoffsForSctHitsPlusDeadCut = std::vector<double>();
1266 m_vecPtCutoffsForSctHitsPlusDeadCut = std::vector<double>();
1267 m_vecvecMinSctHitsPlusDeadAboveEtaPt = std::vector<std::vector<double>>();
1268 }
1269 break;
1270 case CutLevel::Loose :
1271 setCutLevelPrivate(CutLevel::NoCut, overwrite); // if hard overwrite, reset all cuts first. will do nothing if !overwrite
1272 // change the cuts if a hard overwrite is asked for or if the cuts are unset
1273 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1274 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 8;
1275 m_maxOneSharedModule = true;
1276 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1277 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 1;
1278 break;
1279 case CutLevel::LoosePrimary :
1280 setCutLevelPrivate(CutLevel::NoCut, overwrite); // implement loose cuts first
1281 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1282 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 8;
1283 m_maxOneSharedModule = true;
1284 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1285 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 1;
1286 if (overwrite || m_minNSiHitsIfSiSharedHits < 0) m_minNSiHitsIfSiSharedHits = 10;
1287 break;
1288 case CutLevel::TightPrimary :
1289 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1290 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1291 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 9;
1292 m_maxOneSharedModule = true;
1293 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1294 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1296 if (overwrite || m_minNSiHitsAboveEtaCutoff < 0) m_minNSiHitsAboveEtaCutoff = 11;
1298 break;
1299 case CutLevel::LooseMuon :
1300 setCutLevelPrivate(CutLevel::NoCut, overwrite); // reset cuts unless we are doing a soft set
1301 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1302 if (overwrite || m_minNSctHits < 0) m_minNSctHits = 5;
1303 if (overwrite || m_maxNSiHoles >= LOCAL_MAX_INT) m_maxNSiHoles = 2;
1305 if (overwrite || m_maxEtaForTrtHitCuts < 0.) m_maxEtaForTrtHitCuts = 1.9;
1306 if (overwrite || m_minNTrtHitsPlusOutliers < 0) m_minNTrtHitsPlusOutliers = 6;
1308 break;
1309 case CutLevel::LooseElectron :
1310 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1311 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 7;
1312 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1313 break;
1314 case CutLevel::LooseTau :
1315 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1316 if (overwrite || m_minPt < 0.0) m_minPt = 1000.0;
1317 if (overwrite || m_minNSiHits < 0) m_minNSiHits = 7;
1318 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 2;
1319 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.0;
1320 if (overwrite || m_maxZ0 >= LOCAL_MAX_DOUBLE) m_maxZ0 = 1.5;
1321 break;
1322 case CutLevel::MinBias :
1323 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1324 if (overwrite || m_useMinBiasInnermostLayersCut >= 0) m_useMinBiasInnermostLayersCut = 1; // if this is less than 0, it is turned off
1325 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1326 if (overwrite || m_minNSctHits < 0) m_minNSctHits = 6;
1327 if (overwrite || m_minProbAbovePtCutoff < 0.) {
1328 m_minPtForProbCut = 10000.;
1330 }
1331 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1332 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1333 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1334 if (overwrite || m_minPt < 0.) m_minPt = 500.0;
1335 break;
1336 case CutLevel::HILoose:
1337 // HILoose is similar to MinBias, but not identical
1338 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1339 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1341 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1342 if (overwrite || (m_vecPtCutoffsForSctHitsCut.empty()
1343 && m_vecMinNSctHitsAbovePt.empty())) {
1344 m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1345 m_vecMinNSctHitsAbovePt = std::vector<int>({2, 4, 6});
1346 }
1347 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1348 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1349 break;
1350 case CutLevel::HITight:
1351 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1352 // HITight is like HILoose but we require 8 SCT hits and 2 pixel hits
1353 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1354 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1356 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 2;
1357 if (overwrite || (m_vecPtCutoffsForSctHitsCut.empty()
1358 && m_vecMinNSctHitsAbovePt.empty())) {
1359 m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1360 m_vecMinNSctHitsAbovePt = std::vector<int>({4, 6, 8});
1361 }
1362 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.0;
1363 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.0;
1364 if (overwrite || m_maxChiSqperNdf >= LOCAL_MAX_DOUBLE) m_maxChiSqperNdf = 6.0;
1365 break;
1366 case CutLevel::HILooseOptimized:
1367 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1368 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1369 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1371 if (overwrite || (m_vecEtaCutoffsForZ0SinThetaCut.empty() &&
1374 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1376 std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1377 2000, 2500, 3000, 5000, 8000, 12000});
1379 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},
1380 {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},
1381 {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},
1382 {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}});
1383 }
1384 if (overwrite || (m_vecEtaCutoffsForD0Cut.empty() &&
1385 m_vecPtCutoffsForD0Cut.empty() &&
1386 m_vecvecMaxD0AboveEtaPt.empty())){
1387 m_vecEtaCutoffsForD0Cut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1389 std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1390 2000, 2500, 3000, 5000, 8000, 12000});
1392 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},
1393 {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},
1394 {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},
1395 {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}});
1396 }
1397 break;
1398 case CutLevel::HITightOptimized:
1399 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1400 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1401 if (overwrite || m_maxNPixelHoles >= LOCAL_MAX_INT) m_maxNPixelHoles = 0;
1403 if (overwrite || (m_vecEtaCutoffsForZ0SinThetaCut.empty() &&
1406 m_vecEtaCutoffsForZ0SinThetaCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1407 m_vecPtCutoffsForZ0SinThetaCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1408 2000, 2500, 3000, 5000, 8000, 12000});
1410 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},
1411 {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},
1412 {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},
1413 {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}});
1414 }
1415 if (overwrite || (m_vecEtaCutoffsForD0Cut.empty() &&
1416 m_vecPtCutoffsForD0Cut.empty() &&
1417 m_vecvecMaxD0AboveEtaPt.empty())){
1418 m_vecEtaCutoffsForD0Cut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1419 m_vecPtCutoffsForD0Cut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1420 2000, 2500, 3000, 5000, 8000, 12000});
1422 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},
1423 {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},
1424 {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},
1425 {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}});
1426 }
1427 if (overwrite || (m_vecEtaCutoffsForSctHolesCut.empty() &&
1430 m_vecEtaCutoffsForSctHolesCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1431 m_vecPtCutoffsForSctHolesCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1432 2000, 2500, 3000, 5000, 8000, 12000});
1434 std::vector<std::vector<double>>({{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
1435 {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1},
1436 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1437 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}});
1438 }
1439 if (overwrite || (m_vecEtaCutoffsForSctHitsPlusDeadCut.empty() &&
1442 m_vecEtaCutoffsForSctHitsPlusDeadCut = std::vector<double>({0.0, 1.1, 1.6, 2.0});
1443 m_vecPtCutoffsForSctHitsPlusDeadCut = std::vector<double>({500, 600, 700, 800, 900, 1000, 1500,
1444 2000, 2500, 3000, 5000, 8000, 12000});
1446 std::vector<std::vector<double>>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1447 {0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0},
1448 {8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 0, 0, 0},
1449 {7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}});
1450 }
1451 break;
1452 case CutLevel::HILoosePixMod:
1453 // HILoosePixMod is similar to HILoose, but with a modified hit cut on the innermost layers
1454 setCutLevelPrivate(CutLevel::NoCut, overwrite);
1455 if (overwrite || m_maxAbsEta >= LOCAL_MAX_DOUBLE) m_maxAbsEta = 2.5;
1456 if (overwrite) m_useHILoosePixModInnermostLayersCut = true;
1457 if (overwrite || m_minNPixelHits < 0) m_minNPixelHits = 1;
1458 if (overwrite || m_vecPtCutoffsForSctHitsCut.empty()) m_vecPtCutoffsForSctHitsCut = std::vector<double>({0.0, 300.0, 400.0});
1459 if (overwrite || m_vecMinNSctHitsAbovePt.empty()) m_vecMinNSctHitsAbovePt = std::vector<int>({2, 4, 6});
1460 if (overwrite || m_maxD0 >= LOCAL_MAX_DOUBLE) m_maxD0 = 1.5;
1461 if (overwrite || m_maxZ0SinTheta >= LOCAL_MAX_DOUBLE) m_maxZ0SinTheta = 1.5;
1462 break;
1463 default:
1464 ATH_MSG_ERROR("CutLevel not recognized. Cut selection will remain unchanged.");
1465 break;
1466 }
1467}
1468
1469// initialize the map from strings to cut levels
1470const std::unordered_map<std::string, InDet::CutLevel>
1472 {
1473 {"NoCut", InDet::CutLevel::NoCut},
1474 {"Loose", InDet::CutLevel::Loose},
1475 {"LoosePrimary", InDet::CutLevel::LoosePrimary},
1476 {"TightPrimary", InDet::CutLevel::TightPrimary},
1477 {"LooseMuon", InDet::CutLevel::LooseMuon},
1478 {"LooseElectron", InDet::CutLevel::LooseElectron},
1479 {"LooseTau", InDet::CutLevel::LooseTau},
1480 {"MinBias", InDet::CutLevel::MinBias},
1481 {"HILoose", InDet::CutLevel::HILoose},
1482 {"HITight", InDet::CutLevel::HITight},
1483 {"HILooseOptimized", InDet::CutLevel::HILooseOptimized},
1484 {"HITightOptimized", InDet::CutLevel::HITightOptimized},
1485 {"HILoosePixMod", InDet::CutLevel::HILoosePixMod}
1486 };
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.
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< 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:135
bool getCutResult(std::string_view cutName) const
Get the result of a cut, based on the cut name (safer).
Definition AcceptData.h:99
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.
double getFitChiSquare(const 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].
@ 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].
@ 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].