ATLAS Offline Software
Loading...
Searching...
No Matches
TrigHitDVHypoTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
4 * Trigger Hypo Tool, that is aimed at triggering displaced vertex
5 * author Kunihiro Nagano <kunihiro.nagano@cern.ch> - KEK
6*/
7
11#include "GaudiKernel/PhysicalConstants.h"
12#include "TrigHitDVHypoTool.h"
13
14using namespace TrigCompositeUtils;
15
16// ------------------------------------------------------------------------------------------------
17// ------------------------------------------------------------------------------------------------
18
20 const std::string& name,
21 const IInterface* parent )
22 : AthAlgTool( type, name, parent ),
23 m_decisionId( HLT::Identifier::fromToolName( name ) ) {}
24
26
27// ------------------------------------------------------------------------------------------------
28// ------------------------------------------------------------------------------------------------
29
31{
32 ATH_MSG_DEBUG( "Initialization completed successfully:" );
33 ATH_MSG_DEBUG( " cutJetPtGeV = " << m_cutJetPtGeV );
34 ATH_MSG_DEBUG( " cutJetEta = " << m_cutJetEta );
35 ATH_MSG_DEBUG( " effBDT = " << m_effBDT );
36 ATH_MSG_DEBUG( " doSPseed = " << m_doSPseed );
37
38 ATH_MSG_DEBUG( "Tool configured for chain/id: " << m_decisionId );
39
40 return StatusCode::SUCCESS;
41}
42
43// ------------------------------------------------------------------------------------------------
44// ------------------------------------------------------------------------------------------------
45
46float TrigHitDVHypoTool::getBDTthreshold_0eta1(float mu, float eff) const
47{
48 const float defaultBDTthreshold = 0.33482806; // 70% effi at mu=60
49
50 if( mu<10 || 80<mu ) return defaultBDTthreshold;
51 if( eff<0.5 || 1.<eff ) return defaultBDTthreshold;
52
53 // pol4*4 fitting
54 const std::vector<std::vector<float>> par = {
55 { 2.9044277, -6.3516751, -4.0085606, 25.456841, -18.208683 },
56 { 0.066196623, -0.098157640, 0.027455008, -0.19900459, 0.16721183 },
57 { -0.00091570959, 1.4831281e-05, 0.0028768317, -0.00053051617, 0.00040427140 },
58 { 2.5249073e-06, 1.7882097e-06, -7.1741129e-06, -9.7309257e-07, -3.2151707e-05 },
59 { -8.2905419e-08, 3.9337893e-07, -5.8968642e-07, 2.6341441e-07, 2.4551736e-07 }
60 };
61
62 float thres = defaultBDTthreshold;
63 for (size_t i = 0; i < 5; i++) {
64 for (size_t j = 0; j < 5; j++) {
65 float tmp = par[i][j];
66 for (size_t imu = 0; imu < i; imu++) tmp *= mu;
67 for (size_t jeff = 0; jeff < j; jeff++) tmp *= eff;
68 thres += tmp;
69 }
70 }
71
72 return thres;
73}
74
75// ------------------------------------------------------------------------------------------------
76// ------------------------------------------------------------------------------------------------
77
78float TrigHitDVHypoTool::getBDTthreshold_1eta2(float mu, float eff) const
79{
80 const float defaultBDTthreshold = 0.27072057; // 70% effi at mu=60
81
82 if( mu<10 || 80<mu ) return defaultBDTthreshold;
83 if( eff<0.5 || 1.<eff ) return defaultBDTthreshold;
84
85 // pol4*4 fitting
86 const std::vector<std::vector<float>> par = {
87 { 1.8938782, -1.7096217, -8.7938548, 19.779355, -10.656187 },
88 { 0.048863505, -0.18192399, 0.30932576, -0.11527519, -0.13591443 },
89 { -0.00060239060, 0.00096109052, -0.0015378287, -0.0030951666, 0.0063958596 },
90 { 2.5855329e-06, 7.3128949e-06, -6.9676558e-06, 4.2141737e-05, -7.1813827e-05 },
91 { -4.8077006e-08, 1.0646790e-07, -8.0539473e-08, -1.9821312e-07, 3.4713098e-07 }
92 };
93
94 float thres = defaultBDTthreshold;
95 for (size_t i = 0; i < 5; i++) {
96 for (size_t j = 0; j < 5; j++) {
97 float tmp = par[i][j];
98 for (size_t imu = 0; imu < i; imu++) tmp *= mu;
99 for (size_t jeff = 0; jeff < j; jeff++) tmp *= eff;
100 thres += tmp;
101 }
102 }
103
104 return thres;
105}
106
107// ------------------------------------------------------------------------------------------------
108// ------------------------------------------------------------------------------------------------
109
111{
112 const float defaultBDTthreshold = 0.03773; // 70% effi at mu=60
113
114 if( mu<10 || 60<mu ) return defaultBDTthreshold;
115
116 // pol4 fitting
117 const float par0 = 0.404727;
118 const float par1 = -0.00344154;
119 const float par2 = -6.54218e-05;
120 const float par3 = -3.39841e-07;
121 const float par4 = 9.93062e-09;
122
123 float thres = par0 + par1*mu + par2*mu*mu + par3*mu*mu*mu + par4*mu*mu*mu*mu;
124 return thres;
125}
126
127// ------------------------------------------------------------------------------------------------
128// ------------------------------------------------------------------------------------------------
129
130StatusCode TrigHitDVHypoTool::decide( std::vector<HitDVHypoInfo>& toolInputs ) const
131{
132 size_t numTrigger = m_cutJetPtGeV.size();
133 size_t numHitDVs = toolInputs.size();
134
135 ATH_MSG_DEBUG( " Number of HitDVs = " << numHitDVs );
136
137 if ( numTrigger == 1 ) {
138 ATH_MSG_DEBUG( " Applying selection of single for " << m_decisionId );
139 return inclusiveSelection(toolInputs);
140 }
141 else {
142 ATH_MSG_DEBUG( " Applying selection of multiplicity for " << m_decisionId );
143 return multiplicitySelection(toolInputs);
144 }
145
146 return StatusCode::SUCCESS;
147}
148
149// ------------------------------------------------------------------------------------------------
150// ------------------------------------------------------------------------------------------------
151
152StatusCode TrigHitDVHypoTool::inclusiveSelection(std::vector<HitDVHypoInfo>& toolInputs) const
153{
154 bool isJetCutPassed = false;
155 for ( auto& input: toolInputs ) {
156 if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input.previousDecisionsIDs ) ) {
157 if ( decideOnSingleObject( input, 0, true )==true ) {
158 isJetCutPassed = true;
159 break;
160 }
161 }
162 }
163
164 if( ! isJetCutPassed ) return StatusCode::SUCCESS;
165
166 bool isPassed = false;
167 unsigned int idv=0;
168 for ( auto& input: toolInputs ) {
169 ATH_MSG_DEBUG( " --- idv=" << idv << " ---");
170 if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input.previousDecisionsIDs ) ) {
171 if ( decideOnSingleObject( input, 0, false )==true ) {
172 ATH_MSG_DEBUG( " Passed selection --> adding DecisionID");
173 isPassed = true;
175 }
176 } else {
177 ATH_MSG_DEBUG( " Not match DecisionID: " << m_decisionId );
178 }
179 ++idv;
180 }
181
182 ATH_MSG_DEBUG( "Inclusive selection isPassed = " << isPassed);
183 return StatusCode::SUCCESS;
184}
185
186// ------------------------------------------------------------------------------------------------
187// ------------------------------------------------------------------------------------------------
188
189StatusCode TrigHitDVHypoTool::multiplicitySelection(std::vector<HitDVHypoInfo>& toolInputs) const
190{
191 unsigned int n_jetpassed = 0;
192 for ( size_t cutIndex=0; cutIndex < m_cutJetPtGeV.size(); ++cutIndex ) {
193 bool isJetCutPassed = false;
194 for ( auto& input: toolInputs ) {
195 if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input.previousDecisionsIDs ) ) {
196 if ( decideOnSingleObject( input, cutIndex, true )==true ) {
197 isJetCutPassed = true;
198 break;
199 }
200 }
201 }
202 if( isJetCutPassed ) ++n_jetpassed;
203 }
204 if( n_jetpassed < m_cutJetPtGeV.size() ) return StatusCode::SUCCESS;
205
206 //
207 HLT::Index2DVec passingSelection( m_cutJetPtGeV.size() );
208
209 for ( size_t cutIndex=0; cutIndex < m_cutJetPtGeV.size(); ++cutIndex ) {
210 size_t elementIndex{ 0 };
211 for ( auto& input: toolInputs ) {
212 if ( TrigCompositeUtils::passed( m_decisionId.numeric(), input.previousDecisionsIDs ) ) {
213 if ( decideOnSingleObject( input, cutIndex, false ) == true ) {
214 ATH_MSG_DEBUG( "Pass through selection " << m_decisionId << " : Event[" << elementIndex << "]" );
215 passingSelection[cutIndex].push_back( elementIndex );
216 }
217 }
218 else {
219 ATH_MSG_DEBUG( "Not match DecisionID " << m_decisionId );
220 }
221 elementIndex++;
222 }
223 // If no object passes the selection, multipul selection should stop.
224 if ( passingSelection[cutIndex].empty() ) {
225 ATH_MSG_DEBUG( "No object passed selection " << cutIndex << " rejecting" );
226 return StatusCode::SUCCESS;
227 }
228 }
229
230 std::set<size_t> passingIndices;
231 HLT::elementsInUniqueCombinations( passingSelection, passingIndices );
232
233 if ( passingIndices.empty() ) {
234 ATH_MSG_DEBUG( "No track passed through selection " << m_decisionId );
235 return StatusCode::SUCCESS;
236 }
237
238 for ( auto idx: passingIndices ) {
239 ATH_MSG_DEBUG( "track[" << idx << "] passes through Chain/ID " << m_decisionId << " with pT" );
240 TrigCompositeUtils::addDecisionID( m_decisionId.numeric(), toolInputs[idx].decision );
241 }
242
243 return StatusCode::SUCCESS;
244}
245
246// ------------------------------------------------------------------------------------------------
247// ------------------------------------------------------------------------------------------------
248
249bool TrigHitDVHypoTool::decideOnSingleObject( HitDVHypoInfo& input, size_t cutIndex, bool isOnlyJetCut ) const
250{
251 float ptThreshold = m_cutJetPtGeV[cutIndex];
252 float etaThreshold = m_cutJetEta[cutIndex];
253 float eff = m_effBDT[cutIndex];
254
255 const xAOD::TrigComposite* dv = input.hitDV;
256 int seed_type = dv->getDetail<int> ("hitDV_seed_type");
257 float seed_eta = dv->getDetail<float>("hitDV_seed_eta");
258 float seed_pt = dv->getDetail<float>("hitDV_seed_pt");
259
260 // if only jet pt/eta cut
261 if( isOnlyJetCut ) {
262 if( seed_type != SeedType::HLTJet ) return false;
263 if( std::abs(seed_eta) > etaThreshold ) return false;
264 if( seed_pt < ptThreshold ) return false;
265 // passed
266 return true;
267 }
268
269 if( input.isSPOverflow ) return true;
270
271 // normal cut
272 bool doSPseed = m_doSPseed[cutIndex];
273 float BDTthreshold = 0.;
274 float bdt_score = dv->getDetail<float>("hitDV_bdt_score");
275
276 if ( std::abs(seed_eta) < 1 ) {
277 BDTthreshold = getBDTthreshold_0eta1(input.averageMu, eff);
278 } else if ( std::abs(seed_eta) < 2 ) {
279 BDTthreshold = getBDTthreshold_1eta2(input.averageMu, eff);
280 } else {
281 BDTthreshold = getBDTthreshold(input.averageMu);
282 }
283
284 if( ! doSPseed && seed_type==SeedType::SP ) return false;
285 if( seed_type==SeedType::HLTJet && seed_pt < ptThreshold ) return false;
286 if( std::abs(seed_eta) > etaThreshold ) return false;
287 if( bdt_score < BDTthreshold ) return false;
288
289 ATH_MSG_DEBUG( " Selected, cut index / seed_type / seed_eta / bdt_score = " << cutIndex << " / " << seed_type << " / " << seed_eta << " / " << bdt_score);
290
291 return true;
292}
293
294// ------------------------------------------------------------------------------------------------
295// ------------------------------------------------------------------------------------------------
#define ATH_MSG_DEBUG(x)
static const Attributes_t empty
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Property< std::vector< float > > m_cutJetEta
Gaudi::Property< std::vector< bool > > m_doSPseed
Gaudi::Property< std::vector< float > > m_cutJetPtGeV
float getBDTthreshold(float) const
HLT::Identifier m_decisionId
float getBDTthreshold_0eta1(float, float) const
TrigHitDVHypoTool(const std::string &type, const std::string &name, const IInterface *parent)
float getBDTthreshold_1eta2(float, float) const
StatusCode decide(std::vector< HitDVHypoInfo > &) const
decides upon a collection of tracks
virtual StatusCode initialize() override
Gaudi::Property< std::vector< float > > m_effBDT
StatusCode inclusiveSelection(std::vector< HitDVHypoInfo > &) const
StatusCode multiplicitySelection(std::vector< HitDVHypoInfo > &) const
bool decideOnSingleObject(HitDVHypoInfo &, size_t, bool) const
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
void elementsInUniqueCombinations(const Index2DVec &indices, std::set< size_t > &participants, const std::function< bool(const Index1DVec &)> &filter)
std::vector< Index1DVec > Index2DVec
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
void addDecisionID(DecisionID id, Decision *d)
Appends the decision (given as ID) to the decision object.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.