ATLAS Offline Software
Loading...
Searching...
No Matches
TrigHitDVHypoAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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#include "TrigHitDVHypoAlg.h"
11#include "GaudiKernel/SystemOfUnits.h"
13#include "GaudiKernel/PhysicalConstants.h"
16
18#include "CxxUtils/phihelper.h"
20
21#include "TFile.h"
22#include "TTree.h"
23
24#include <vector>
25#include <unordered_map>
26
41
43
44// ------------------------------------------------------------------------------------------------
45// ------------------------------------------------------------------------------------------------
46
47TrigHitDVHypoAlg::TrigHitDVHypoAlg( const std::string& name,
48 ISvcLocator* pSvcLocator ) :
49 ::HypoBase( name, pSvcLocator ),
50 m_lumiBlockMuTool("LumiBlockMuTool/LumiBlockMuTool")
51{}
52
53// ------------------------------------------------------------------------------------------------
54// ------------------------------------------------------------------------------------------------
55
57{
60 CHECK( m_hypoTools.retrieve() );
61 for ( auto & tool: m_hypoTools ) {
62 ATH_MSG_VERBOSE( "+++++ Hypo Tool name: " << tool->name() );
63 std::cmatch results;
64 if( std::regex_search(tool->name().c_str(),results,std::regex("hitdvjet(\\d+)_(\\w+)_")) ) {
65 std::string sth = results[1].str();
66 std::string swp = results[2].str();
67 ATH_MSG_VERBOSE( " thres = " << sth << ", wp = " << swp );
68 int thres = std::stoi(sth);
69 if( thres < m_tools_lowest_jetEt ) m_tools_lowest_jetEt = thres;
70 if( swp == "loose" && m_tools_loosest_wp >= 1 ) m_tools_loosest_wp = 1;
71 if( swp == "medium" && m_tools_loosest_wp >= 2 ) m_tools_loosest_wp = 2;
72 if( swp == "tight" && m_tools_loosest_wp >= 3 ) m_tools_loosest_wp = 3;
73 }
74 }
75 ATH_MSG_DEBUG( "Lowest jetEt used in hypo tools = " << m_tools_lowest_jetEt << " (GeV)" );
76 ATH_MSG_DEBUG( "Loosest WP used in hypo tools = " << m_tools_loosest_wp << " (loose=1,medium=2,tight=3)");
77 // loose : eta<2.0, SP seed=true, BDT eff=0.9
78 // medium: eta<2.0, SP seed=false, BDT eff=0.75
79 // tight : eta<1.0, SP seed=false, BDT eff=0.75
80
81 CHECK( m_jetsKey.initialize() );
82 CHECK( m_hitDVKey.initialize());
83 CHECK( m_tracksKey.initialize());
84 CHECK( m_lumiDataKey.initialize(!m_isMC) );
86
87 if ( !m_monTool.empty() ) CHECK( m_monTool.retrieve() );
88
89 ATH_CHECK(m_beamSpotKey.initialize());
90 ATH_CHECK(m_spacePointTool.retrieve() );
91
92 // MVAUtils BDT initialisation
93 // could make this configurable as a property
94 std::string weightfile[2];
95 weightfile[0] = PathResolver::find_calib_file("TrigHitDVHypo/HitDV.BDT.weights.0eta1.v22a.root");
96 weightfile[1] = PathResolver::find_calib_file("TrigHitDVHypo/HitDV.BDT.weights.1eta2.v22a.root");
97 for (unsigned int i=0; i<2; ++i) {
98 std::unique_ptr<TFile> rootFile(TFile::Open(weightfile[i].c_str(), "READ"));
99 if (!rootFile) {
100 ATH_MSG_ERROR("Can not open BDT root file: " << weightfile[i] );
101 return StatusCode::FAILURE;
102 }
103 std::unique_ptr<TTree> tree((TTree*)rootFile->Get("BDT"));
104 if (!tree) {
105 ATH_MSG_ERROR("Can not find BDT tree in file: " << weightfile[i]);
106 return StatusCode::FAILURE;
107 }
108 ATH_MSG_INFO("Loading BDT tree from file: " << weightfile[i]);
109 m_bdt_eta[i] = std::make_unique<MVAUtils::BDT>(tree.get());
110 }
111
112 return StatusCode::SUCCESS;
113}
114
115// ------------------------------------------------------------------------------------------------
116// ------------------------------------------------------------------------------------------------
117
118StatusCode TrigHitDVHypoAlg::execute( const EventContext& context ) const
119{
120
121 const TrigRoiDescriptor roi = TrigRoiDescriptor(0, -4.5, 4.5, 0, -M_PI, M_PI, 0, -168.0, 168.0);
122 std::vector<TrigSiSpacePointBase> convertedSpacePoints;
123 convertedSpacePoints.reserve(5000);
124 int mnt_roi_nSPsPIX;
125 int mnt_roi_nSPsSCT;
126 ATH_CHECK(m_spacePointTool->getSpacePoints(roi, convertedSpacePoints, mnt_roi_nSPsPIX, mnt_roi_nSPsSCT, context));
127
128 // monitoring
129 auto mon_n_dvtrks = Monitored::Scalar<int>( "n_dvtrks", 0 );
130 auto mon_n_dvsps = Monitored::Scalar<int>( "n_dvsps", 0 );
131 auto mon_n_jetseeds = Monitored::Scalar<int>( "n_jetseeds", 0 );
132 auto mon_n_jetseedsdel= Monitored::Scalar<int>( "n_jetseedsdel",0 );
133 auto mon_n_spseeds = Monitored::Scalar<int>( "n_spseeds", 0 );
134 auto mon_n_spseedsdel = Monitored::Scalar<int>( "n_spseedsdel", 0 );
135 auto mon_average_mu = Monitored::Scalar<float>( "average_mu", 0.);
136 auto monitorIt = Monitored::Group( m_monTool, mon_n_dvtrks, mon_n_dvsps, mon_n_jetseeds, mon_n_jetseedsdel, mon_n_spseeds, mon_n_spseedsdel, mon_average_mu );
137
138 // previous decisions
139 ATH_MSG_DEBUG( "Retrieving pervious decision: \"" << decisionInput().key() << "\"" );
140 auto previousDecisionsHandle = SG::makeHandle( decisionInput(), context );
141 ATH_CHECK( previousDecisionsHandle.isValid() );
142
143 ATH_MSG_DEBUG( "Running with " << previousDecisionsHandle->size() << " previous decisions" );
144 if( previousDecisionsHandle->size()!=1 ) {
145 ATH_MSG_ERROR( "Previous decision handle size is not 1. It is" << previousDecisionsHandle->size() );
146 return StatusCode::FAILURE;
147 }
148 const Decision * previousDecision = previousDecisionsHandle->at(0);
149
150 TrigCompositeUtils::DecisionIDContainer previousDecisionIDs;
151 TrigCompositeUtils::decisionIDs(previousDecision, previousDecisionIDs);
152 ATH_MSG_DEBUG( "IDs of active legs:" );
153 for(auto decisionID: previousDecisionIDs) { ATH_MSG_DEBUG( " " << decisionID ); }
154
155 // new output decisions
156 ATH_MSG_DEBUG( "Creating new output decision handle" );
158 auto outputDecisions = outputHandle.ptr();
159
160 // input objects
161
162 // jets
163 auto jetsHandle = SG::makeHandle(m_jetsKey, context );
164 ATH_CHECK( jetsHandle.isValid() );
165 ATH_MSG_DEBUG( "jet handle size: " << jetsHandle->size() );
166
167 const xAOD::JetContainer* jetsContainer = jetsHandle.get();
168 if( jetsContainer == nullptr ) {
169 ATH_MSG_ERROR( "ERROR Cannot get jet container" );
170 return StatusCode::FAILURE;
171 }
172 bool isJetEtPassToolsCut = false;
173 float jetEtaToolsCut = 2.0;
174 if( m_tools_loosest_wp >= 3 ) jetEtaToolsCut = 1.0;
175 for ( const xAOD::Jet* jet : *jetsContainer ) {
176 float jet_pt = static_cast<float>(jet->pt() / Gaudi::Units::GeV );
177 float jet_eta = static_cast<float>(jet->eta());
178 if( jet_pt >= m_tools_lowest_jetEt && std::abs(jet_eta)<=jetEtaToolsCut ) {
179 isJetEtPassToolsCut = true;
180 break;
181 }
182 }
183
184 auto tracks = SG::makeHandle( m_tracksKey, context );
185 ATH_CHECK(tracks.isValid());
186
187 std::vector<HitDVSeed> hitDVSeedsContainer;
188 std::vector<HitDVTrk> hitDVTrksContainer;
189 std::vector<HitDVSpacePoint> hitDVSPsContainer;
190
191
192 ATH_CHECK( findHitDV(context, convertedSpacePoints, *tracks, hitDVSeedsContainer, hitDVTrksContainer, hitDVSPsContainer) );
193
194 mon_n_dvtrks = hitDVTrksContainer.size();
195 mon_n_dvsps = hitDVSPsContainer.size();
196 const unsigned int N_MAX_SP_STORED = 100000;
197 bool isSPOverflow = false;
198 if( hitDVSPsContainer.size() >= N_MAX_SP_STORED ) isSPOverflow = true;
199 ATH_MSG_DEBUG( "hitDVSP size=" << mon_n_dvsps );
200
201 // average mu
202 float averageMu = 0;
203 if( m_isMC ) {
204 if( m_lumiBlockMuTool ) {
205 averageMu = static_cast<float>(m_lumiBlockMuTool->averageInteractionsPerCrossing(context));
206 ATH_MSG_DEBUG( "offline averageMu = " << averageMu );
207 }
208 }
209 else {
211 averageMu = lcd.cptr()->lbAverageInteractionsPerCrossing();
212 ATH_MSG_DEBUG( "online averageMu = " << averageMu );
213 }
214 mon_average_mu = averageMu;
215
216 // find seeds based on HLT jets
217 std::vector<float> jetSeeds_pt;
218 std::vector<float> jetSeeds_eta;
219 std::vector<float> jetSeeds_phi;
220 ATH_CHECK( findJetSeeds(jetsContainer, m_jetSeed_ptMin, m_jetSeed_etaMax, jetSeeds_pt, jetSeeds_eta, jetSeeds_phi) );
221 int n_alljetseeds = jetSeeds_eta.size();
222 ATH_CHECK( selectSeedsNearby(hitDVSeedsContainer, jetSeeds_eta, jetSeeds_phi, jetSeeds_pt) );
223 mon_n_jetseeds = jetSeeds_eta.size();
224 mon_n_jetseedsdel = n_alljetseeds - jetSeeds_eta.size();
225
226 // find seeds based on SP frac itself
227 std::vector<float> spSeeds_eta;
228 std::vector<float> spSeeds_phi;
229 std::vector<float> void_pt;
230 int n_allspseeds = 0;
231 if( m_tools_loosest_wp <= 1 ) {
232 ATH_CHECK( findSPSeeds(context, hitDVSPsContainer, spSeeds_eta, spSeeds_phi) );
233 n_allspseeds = spSeeds_eta.size();
234 ATH_CHECK( selectSeedsNearby(hitDVSeedsContainer, spSeeds_eta, spSeeds_phi, void_pt) );
235 mon_n_spseeds = spSeeds_eta.size();
236 mon_n_spseedsdel = n_allspseeds - spSeeds_eta.size();
237 }
238 else {
239 mon_n_spseeds = 0;
240 mon_n_spseedsdel = 0;
241 }
242
243 // output EDM object
244 auto hitDVContainer = std::make_unique<xAOD::TrigCompositeContainer>();
245 auto hitDVContainerAux = std::make_unique<xAOD::TrigCompositeAuxContainer>();
246 hitDVContainer->setStore(hitDVContainerAux.get());
247
248 xAOD::TrigCompositeContainer* dvContainer = hitDVContainer.get();
249 std::vector<TrigHitDVHypoTool::HitDVHypoInfo> hitDVHypoInputs;
250 std::unordered_map<Decision*, size_t> mapDecIdx;
251
252 // calculate BDT and create hitDVContainer EDM
253 if( isJetEtPassToolsCut ) {
254 const float preselBDTthreshold = -0.6;
255
256 int n_passed_jet = 0;
257 int seed_type = SeedType::HLTJet;
258 ATH_CHECK( calculateBDT(hitDVSPsContainer, hitDVTrksContainer, jetSeeds_pt, jetSeeds_eta, jetSeeds_phi, preselBDTthreshold, seed_type, dvContainer, n_passed_jet) );
259
260 int n_passed_sp = 0;
261 if( m_tools_loosest_wp <= 1 ) {
262 seed_type = SeedType::SP;
263 ATH_CHECK( calculateBDT(hitDVSPsContainer, hitDVTrksContainer, void_pt, spSeeds_eta, spSeeds_phi, preselBDTthreshold, seed_type, dvContainer, n_passed_sp) );
264 }
265
266 ATH_MSG_DEBUG( "nr of dv container / jet-seeded / sp-seed candidates = " << dvContainer->size() << " / " << n_passed_jet << " / " << n_passed_sp );
267
268 // Prepare inputs to HypoTool
269 for ( auto dv : *dvContainer ) {
270 Decision* newDecision = TrigCompositeUtils::newDecisionIn( outputDecisions, previousDecision, TrigCompositeUtils::hypoAlgNodeName(), context);
271 mapDecIdx.emplace( newDecision, dv->index() );
272 TrigHitDVHypoTool::HitDVHypoInfo hypoInfo{ newDecision, isSPOverflow, averageMu, dv, previousDecisionIDs };
273 hitDVHypoInputs.push_back( std::move(hypoInfo) );
274 }
275 }
276
277 // monitor
278 ATH_CHECK( doMonitor(dvContainer) );
279
280 // Loop over all hypoToolinputs and get their decisions
281 for ( auto & tool: m_hypoTools ) {
282 ATH_MSG_DEBUG( "+++++ Now computing decision for " << tool->name() );
283 ATH_CHECK( tool->decide( hitDVHypoInputs ) );
284 }
285
286 // record hitDV object
288 ATH_CHECK( hitDVHandle.record( std::move( hitDVContainer ), std::move( hitDVContainerAux ) ) );
289 ATH_MSG_DEBUG( "recorded hitDV object to SG" );
290
291 DecisionContainer::iterator it = outputDecisions->begin();
292 while(it != outputDecisions->end()) {
293 ATH_MSG_DEBUG( "+++++ outputDecision: " << *it << " +++++" );
294 if ( allFailed( *it ) ) {
295 ATH_MSG_DEBUG( "---> all failed, erasing" );
296 it = outputDecisions->erase(it);
297 } else {
298 ATH_MSG_DEBUG( "---> not all failed" );
299
300 // Link hitDV object
301 auto decision = *it;
302 size_t idx = mapDecIdx.at(*it);
303
305 ATH_CHECK( dvEL.isValid() );
306
307 ATH_CHECK( decision->setObjectLink<xAOD::TrigCompositeContainer>(featureString(), dvEL) );
308
309 ATH_MSG_DEBUG(*decision);
310 ++it;
311 }
312 }
313
314 //
315 ATH_CHECK( hypoBaseOutputProcessing(outputHandle) );
316
317 //
318 return StatusCode::SUCCESS;
319}
320
321// ------------------------------------------------------------------------------------------------
322// ------------------------------------------------------------------------------------------------
323
324float TrigHitDVHypoAlg::deltaR2(float eta_1, float phi_1, float eta_2, float phi_2) const {
325 float dPhi = CxxUtils::wrapToPi(phi_1 - phi_2);
326 float dEta = eta_1 - eta_2;
327 return (dPhi*dPhi)+(dEta*dEta);
328}
329
330// ------------------------------------------------------------------------------------------------
331// ------------------------------------------------------------------------------------------------
332
333int TrigHitDVHypoAlg::getSPLayer(int layer, float eta) const
334{
335 float abseta = std::fabs(eta);
336
337 // if Pixel/SCT barrel, layer number is as it is
338 if( 0<=layer && layer <=7 ) {
339 ATH_MSG_VERBOSE("layer=" << layer << ", eta=" << abseta);
340 return layer;
341 }
342
343 // for Pixel/SCT endcap, assign layer number of 0-7 depending on eta range
344
345 int base = 0;
346
347 //
348 const float PixBR6limit = 1.29612;
349 const float PixBR5limit = 1.45204;
350 const float PixBR4limit = 1.64909;
351 const float PixBR3limit = 1.90036;
352 const float PixBR2limit = 2.2146;
353
354 // Pixel Endcap #1
355 base = 8;
356 if( layer==base || layer==(base+12) ) {
357 ATH_MSG_VERBOSE("Pix EC1, eta=" << abseta);
358 if( abseta > PixBR2limit ) return 2;
359 return 3;
360 }
361
362 // Pixel Endcap #2
363 base = 9;
364 if( layer==base || layer==(base+12) ) {
365 ATH_MSG_VERBOSE("Pix EC2, eta=" << abseta);
366 if( abseta > PixBR2limit ) return 2;
367 return 3;
368 }
369
370 // Pixel Endcap #3
371 base = 10;
372 if( layer==base || layer==(base+12) ) {
373 ATH_MSG_VERBOSE("Pix EC3, eta=" << abseta);
374 return 3;
375 }
376
377 // SCT Endcap #1
378 base = 11;
379 if( layer==base || layer==(base+12) ) {
380 ATH_MSG_VERBOSE("Sct EC1, eta=" << abseta);
381 if( abseta < PixBR6limit ) return 7;
382 else if( abseta < PixBR5limit ) return 6;
383 return 5;
384 }
385
386 // SCT Endcap #2
387 base = 12;
388 if( layer==base || layer==(base+12) ) {
389 ATH_MSG_VERBOSE("Sct EC2, eta=" << abseta);
390 if( abseta < PixBR5limit ) return 7;
391 else if( abseta < PixBR4limit ) return 6;
392 return 4;
393 }
394
395 // SCT Endcap #3
396 base = 13;
397 if( layer==base || layer==(base+12) ) {
398 ATH_MSG_VERBOSE("Sct EC3, eta=" << abseta);
399 if( abseta < PixBR4limit ) return 7;
400 return 5;
401 }
402
403 // SCT Endcap #4
404 base = 14;
405 if( layer==base || layer==(base+12) ) {
406 ATH_MSG_VERBOSE("Sct EC4, eta=" << abseta);
407 if( abseta < PixBR4limit ) return 6;
408 else if( abseta < PixBR3limit ) return 6;
409 return 4;
410 }
411
412 // SCT Endcap #5
413 base = 15;
414 if( layer==base || layer==(base+12) ) {
415 ATH_MSG_VERBOSE("Sct EC5, eta=" << abseta);
416 if( abseta < PixBR3limit ) return 7;
417 return 5;
418 }
419
420 // SCT Endcap #6
421 base = 16;
422 if( layer==base || layer==(base+12) ) {
423 ATH_MSG_VERBOSE("Sct EC6, eta=" << abseta);
424 if( abseta < PixBR3limit ) return 6;
425 return 4;
426 }
427
428 // SCT Endcap #7
429 base = 17;
430 if( layer==base || layer==(base+12) ) {
431 ATH_MSG_VERBOSE("Sct EC7, eta=" << abseta);
432 if( abseta < PixBR3limit ) return 7;
433 return 5;
434 }
435
436 // SCT Endcap #8
437 base = 18;
438 if( layer==base || layer==(base+12) ) {
439 ATH_MSG_VERBOSE("Sct EC8, eta=" << abseta);
440 if( abseta < PixBR3limit ) return 7;
441 return 6;
442 }
443
444 // SCT Endcap #9
445 base = 19;
446 if( layer==base || layer==(base+12) ) {
447 ATH_MSG_VERBOSE("Sct EC9, eta=" << abseta);
448 return 7;
449 }
450
451 return 0;
452}
453
454// ------------------------------------------------------------------------------------------------
455// ------------------------------------------------------------------------------------------------
456
458{
459 auto mon_ly0_spfr = Monitored::Collection(
460 "ly0_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly0_sp_frac"); });
461 auto mon_ly1_spfr = Monitored::Collection(
462 "ly1_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly1_sp_frac"); });
463 auto mon_ly2_spfr = Monitored::Collection(
464 "ly2_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly2_sp_frac"); });
465 auto mon_ly3_spfr = Monitored::Collection(
466 "ly3_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly3_sp_frac"); });
467 auto mon_ly4_spfr = Monitored::Collection(
468 "ly4_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly4_sp_frac"); });
469 auto mon_ly5_spfr = Monitored::Collection(
470 "ly5_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly5_sp_frac"); });
471 auto mon_ly6_spfr = Monitored::Collection(
472 "ly6_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly6_sp_frac"); });
473 auto mon_ly7_spfr = Monitored::Collection(
474 "ly7_spfr", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_ly7_sp_frac"); });
475 auto mon_bdtscore = Monitored::Collection(
476 "bdtscore", *dvContainer, [&](const Decision* d){ return d->getDetail<float>("hitDV_bdt_score"); });
477 auto mon_n_qtrk = Monitored::Collection(
478 "n_qtrk", *dvContainer, [&](const Decision* d){ return d->getDetail<int>("hitDV_n_track_qual"); });
479
480 // fill CutMask to split spacespoints into eta regions
481 std::vector<char> mask_eta1(dvContainer->size(), 0);
482 std::vector<char> mask_1eta2(dvContainer->size(), 0);
483 auto mon_eta1_mask = Monitored::Collection( "cutEta1", mask_eta1 );
484 auto mon_1eta2_mask = Monitored::Collection( "cut1Eta2", mask_1eta2 );
485
486 for (size_t i = 0; i<dvContainer->size(); ++i) {
487 const Decision* dv = (*dvContainer)[i];
488
489 // do not fill sp-seeded candidates
490 if( dv->getDetail<int>("hitDV_seed_type") == SeedType::SP ) continue;
491
492 // fill the cut mask according to eta range
493 static const std::string seedEtaStr{"hitDV_seed_eta"};
494 const float abs_eta = std::abs(dv->getDetail<float>(seedEtaStr));
495 if ( abs_eta < 1.0 ) mask_eta1[i] = 1;
496 else if( abs_eta < 2.0 ) mask_1eta2[i] = 1;
497 }
498
499 auto monitorIt = Monitored::Group( m_monTool,
500 mon_ly0_spfr, mon_ly1_spfr, mon_ly2_spfr, mon_ly3_spfr,
501 mon_ly4_spfr, mon_ly5_spfr, mon_ly6_spfr, mon_ly7_spfr,
502 mon_n_qtrk, mon_bdtscore, mon_eta1_mask, mon_1eta2_mask );
503
504 return StatusCode::SUCCESS;
505}
506
507// ------------------------------------------------------------------------------------------------
508// ------------------------------------------------------------------------------------------------
509
510StatusCode TrigHitDVHypoAlg::calculateBDT(const std::vector<HitDVSpacePoint>& spsContainer,
511 const std::vector<HitDVTrk>& trksContainer,
512 const std::vector<float>& seeds_pt,
513 const std::vector<float>& seeds_eta, const std::vector<float>& seeds_phi,
514 const float& cutBDTthreshold, const int seed_type,
515 xAOD::TrigCompositeContainer* dvContainer, int& n_passed) const
516{
517 if( seeds_eta.size() != seeds_phi.size() ) return StatusCode::SUCCESS;
518 n_passed = 0;
519
520 for(unsigned int iseed=0; iseed<seeds_eta.size(); iseed++) {
521
522 float seed_eta = seeds_eta[iseed];
523 float seed_phi = seeds_phi[iseed];
524
525 ATH_MSG_VERBOSE("+++++ seed eta: " << seed_eta << ", phi:" << seed_phi << " +++++");
526
527 // loop on space points
528 const int N_LAYER = 8;
529 const float DR_SQUARED_TO_REF_CUT = 0.16; // const float DR_TO_REF_CUT = 0.4;
530
531 int n_sp_injet = 0;
532 int n_sp_injet_usedByTrk = 0;
533 int v_n_sp_injet[N_LAYER];
534 int v_n_sp_injet_usedByTrk[N_LAYER];
535 for(int i=0; i<N_LAYER; i++) { v_n_sp_injet[i]=0; v_n_sp_injet_usedByTrk[i]=0; }
536
537 for ( const auto & spData : spsContainer ) {
538 // match within dR
539 float sp_eta = spData.eta;
540 float sp_phi = spData.phi;
541 float dR2 = deltaR2(sp_eta,sp_phi,seed_eta,seed_phi);
542 if( dR2 > DR_SQUARED_TO_REF_CUT ) continue;
543
544 //
545 int sp_layer = (int)spData.layer;
546 int sp_trkid = (int)spData.usedTrkId;
547 bool isUsedByTrk = (sp_trkid != -1);
548
549 int ilayer = getSPLayer(sp_layer,sp_eta);
550
551 if( ilayer<=7 ) { // Pixel barrel or Sct barrel
552 n_sp_injet++;
553 v_n_sp_injet[ilayer]++;
554 if( isUsedByTrk ) {
555 n_sp_injet_usedByTrk++;
556 v_n_sp_injet_usedByTrk[ilayer]++;
557 }
558 }
559 }
560 ATH_MSG_VERBOSE("nr of SPs in jet: usedByTrk / all = " << n_sp_injet_usedByTrk << " / " << n_sp_injet);
561 float v_ly_sp_frac[N_LAYER];
562 for(int i=0; i<N_LAYER; i++) {
563 float frac = 0.;
564 if( v_n_sp_injet[i] > 0 ) frac = 1.0 - static_cast<float>(v_n_sp_injet_usedByTrk[i]) / static_cast<float>(v_n_sp_injet[i]);
565 v_ly_sp_frac[i] = frac;
566 ATH_MSG_VERBOSE("Layer " << i << ": frac=" << v_ly_sp_frac[i] << ", n used / all = " << v_n_sp_injet_usedByTrk[i] << " / " << v_n_sp_injet[i]);
567 }
568
569 // loop on tracks
570 const float TRK_PT_GEV_CUT = 2.0;
571
572 unsigned int n_qtrk_injet = 0;
573 for ( const auto& trk : trksContainer ) {
574 float trk_ptGeV = trk.pt;
575 trk_ptGeV /= Gaudi::Units::GeV;
576 if( trk_ptGeV < TRK_PT_GEV_CUT ) continue;
577 float dR2 = deltaR2(trk.eta,trk.phi,seed_eta,seed_phi);
578 if( dR2 > DR_SQUARED_TO_REF_CUT ) continue;
579 n_qtrk_injet++;
580 }
581 ATH_MSG_DEBUG("nr of all / quality tracks matched = " << trksContainer.size() << " / " << n_qtrk_injet);
582
583 // evaluate BDT
584 bool isSeedOutOfRange = false;
585 if( n_qtrk_injet == 0 ) {
586 isSeedOutOfRange = true;
587 for(int i=0; i<N_LAYER; i++) {
588 if( std::fabs(v_ly_sp_frac[i]) > 1e-3 ) {
589 isSeedOutOfRange = false; break;
590 }
591 }
592 }
593 float bdt_score = -2.0;
594 if( ! isSeedOutOfRange ) {
595 const std::vector<float> input_values = {
596 static_cast<float>(n_qtrk_injet),
597 v_ly_sp_frac[0],
598 v_ly_sp_frac[1],
599 v_ly_sp_frac[2],
600 v_ly_sp_frac[3],
601 v_ly_sp_frac[4],
602 v_ly_sp_frac[5],
603 v_ly_sp_frac[6],
604 v_ly_sp_frac[7] };
605
606 if ( std::abs(seed_eta) < 1 ) {
607 bdt_score = m_bdt_eta[0]->GetClassification(input_values);
608 } else if ( std::abs(seed_eta) < 2 ) {
609 bdt_score = m_bdt_eta[1]->GetClassification(input_values);
610 }
611 }
612
613 // BDT threshold
614 if( bdt_score < cutBDTthreshold ) continue;
615
616 // passed selection
617 ATH_MSG_VERBOSE("Passed selection");
618 n_passed++;
619
620 // create EDM object
622 dv->makePrivateStore();
623 dvContainer->push_back(dv);
624
625 float seed_pt = 0;
626 if ( seed_type == SeedType::HLTJet ) seed_pt = seeds_pt[iseed];
627 dv->setDetail<float>("hitDV_seed_pt", seed_pt);
628 dv->setDetail<float>("hitDV_seed_eta", seed_eta);
629 dv->setDetail<float>("hitDV_seed_phi", seed_phi);
630 dv->setDetail<int> ("hitDV_seed_type", seed_type);
631 dv->setDetail<int> ("hitDV_n_track_qual", n_qtrk_injet);
632 dv->setDetail<float>("hitDV_ly0_sp_frac", v_ly_sp_frac[0]);
633 dv->setDetail<float>("hitDV_ly1_sp_frac", v_ly_sp_frac[1]);
634 dv->setDetail<float>("hitDV_ly2_sp_frac", v_ly_sp_frac[2]);
635 dv->setDetail<float>("hitDV_ly3_sp_frac", v_ly_sp_frac[3]);
636 dv->setDetail<float>("hitDV_ly4_sp_frac", v_ly_sp_frac[4]);
637 dv->setDetail<float>("hitDV_ly5_sp_frac", v_ly_sp_frac[5]);
638 dv->setDetail<float>("hitDV_ly6_sp_frac", v_ly_sp_frac[6]);
639 dv->setDetail<float>("hitDV_ly7_sp_frac", v_ly_sp_frac[7]);
640 dv->setDetail<float>("hitDV_bdt_score", bdt_score);
641
642 ATH_MSG_VERBOSE("Created a new entry EDM");
643 }
644 ATH_MSG_DEBUG("nr of BDT passed = " << n_passed);
645
646 //
647 return StatusCode::SUCCESS;
648}
649
650// ------------------------------------------------------------------------------------------------
651// ------------------------------------------------------------------------------------------------
652
653StatusCode TrigHitDVHypoAlg::findJetSeeds(const xAOD::JetContainer* jetsContainer, const float cutJetPt, const float cutJetEta,
654 std::vector<float>& jetSeeds_pt, std::vector<float>& jetSeeds_eta, std::vector<float>& jetSeeds_phi) const
655{
656 std::vector<float> mnt_jet_pt;
657 std::vector<float> mnt_jet_eta;
658 auto mon_jet_pt = Monitored::Collection("jet_pt", mnt_jet_pt);
659 auto mon_jet_eta = Monitored::Collection("jet_eta", mnt_jet_eta);
660 auto monitorIt = Monitored::Group( m_monTool, mon_jet_pt, mon_jet_eta );
661
662 ATH_MSG_VERBOSE("looking for jet seed with pt cut=" << cutJetPt << ", eta cut=" << cutJetEta);
663 for ( const xAOD::Jet* jet : *jetsContainer ) {
664 float jet_pt = static_cast<float>(jet->pt() / Gaudi::Units::GeV );
665 if( jet_pt < cutJetPt ) {
666 ATH_MSG_VERBOSE("Fails jet pt cut, pt = " << jet_pt);
667 continue;
668 }
669 mnt_jet_pt.push_back(jet_pt);
670 float jet_eta = static_cast<float>(jet->eta());
671 mnt_jet_eta.push_back(jet_eta);
672 if( std::fabs(jet_eta) > cutJetEta ) {
673 ATH_MSG_VERBOSE("Fails jet eta cut, eta = " << jet_eta);
674 continue;
675 }
676 float jet_phi = static_cast<float>(jet->phi());
677 jetSeeds_pt.push_back(jet_pt);
678 jetSeeds_eta.push_back(jet_eta);
679 jetSeeds_phi.push_back(jet_phi);
680 }
681 ATH_MSG_VERBOSE("nr of jet seeds=" << jetSeeds_eta.size());
682
683 return StatusCode::SUCCESS;
684}
685
686// ------------------------------------------------------------------------------------------------
687// ------------------------------------------------------------------------------------------------
688
689StatusCode TrigHitDVHypoAlg::findSPSeeds( const EventContext& ctx, const std::vector<HitDVSpacePoint>& spsContainer,
690 std::vector<float>& seeds_eta, std::vector<float>& seeds_phi ) const
691{
692 seeds_eta.clear();
693 seeds_phi.clear();
694
695 const int NBINS_ETA = 50;
696 const float ETA_MIN = -2.5;
697 const float ETA_MAX = 2.5;
698
699 const int NBINS_PHI = 80;
700 const float PHI_MIN = -4.0;
701 const float PHI_MAX = 4.0;
702
703 char hname[64];
704
705 unsigned int slotnr = ctx.slot();
706 unsigned int subSlotnr = ctx.subSlot();
707
708 sprintf(hname,"hitdv_s%u_ss%u_ly6_h2_nsp",slotnr,subSlotnr);
709 std::unique_ptr<TH2F> ly6_h2_nsp = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
710 sprintf(hname,"hitdv_s%u_ss%u_ly7_h2_nsp",slotnr,subSlotnr);
711 std::unique_ptr<TH2F> ly7_h2_nsp = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
712
713 sprintf(hname,"hitdv_s%u_ss%u_ly6_h2_nsp_notrk",slotnr,subSlotnr);
714 std::unique_ptr<TH2F> ly6_h2_nsp_notrk = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
715 sprintf(hname,"hitdv_s%u_ss%u_ly7_h2_nsp_notrk",slotnr,subSlotnr);
716 std::unique_ptr<TH2F> ly7_h2_nsp_notrk = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
717
718 for ( const auto& spData : spsContainer ) {
719 int16_t sp_layer = spData.layer;
720 float sp_eta = spData.eta;
721 int ilayer = getSPLayer(sp_layer,sp_eta);
722 if( ilayer<6 ) continue;
723
724 int sp_trkid = (int)spData.usedTrkId;
725 bool isUsedByTrk = (sp_trkid != -1);
726 float sp_phi = spData.phi;
727
728 bool fill_out_of_pi = false;
729 float sp_phi2 = 0;
730 if( sp_phi < 0 ) {
731 sp_phi2 = 2*TMath::Pi() + sp_phi;
732 if( sp_phi2 < PHI_MAX ) fill_out_of_pi = true;
733 }
734 else {
735 sp_phi2 = -2*TMath::Pi() + sp_phi;
736 if( PHI_MIN < sp_phi2 ) fill_out_of_pi = true;
737 }
738 if( ilayer==6 ) {
739 ly6_h2_nsp->Fill(sp_eta,sp_phi);
740 if( fill_out_of_pi ) ly6_h2_nsp->Fill(sp_eta,sp_phi2);
741 if( ! isUsedByTrk ) ly6_h2_nsp_notrk->Fill(sp_eta,sp_phi);
742 if( ! isUsedByTrk && fill_out_of_pi) ly6_h2_nsp_notrk->Fill(sp_eta,sp_phi2);
743 }
744 if( ilayer==7 ) {
745 ly7_h2_nsp->Fill(sp_eta,sp_phi);
746 if( fill_out_of_pi ) ly7_h2_nsp->Fill(sp_eta,sp_phi2);
747 if( ! isUsedByTrk ) ly7_h2_nsp_notrk->Fill(sp_eta,sp_phi);
748 if( ! isUsedByTrk && fill_out_of_pi) ly7_h2_nsp_notrk->Fill(sp_eta,sp_phi2);
749 }
750 }
751
752 ATH_MSG_VERBOSE("looking for ly6/ly6 doublet seeds");
753
754 // (idx, sort/weight, eta, phi)
755 std::vector<std::tuple<int,float,float,float>> QT;
756
757 for(int ly6_ieta=1; ly6_ieta<=NBINS_ETA; ly6_ieta++) {
758 float ly6_eta = (ly6_h2_nsp->GetXaxis()->GetBinLowEdge(ly6_ieta) + ly6_h2_nsp->GetXaxis()->GetBinUpEdge(ly6_ieta))/2.0;
759 for(int ly6_iphi=1; ly6_iphi<=NBINS_PHI; ly6_iphi++) {
760 float ly6_phi = (ly6_h2_nsp->GetYaxis()->GetBinLowEdge(ly6_iphi) + ly6_h2_nsp->GetYaxis()->GetBinUpEdge(ly6_iphi))/2.0;
761
762 float ly6_nsp = ly6_h2_nsp ->GetBinContent(ly6_ieta,ly6_iphi);
763 float ly6_nsp_notrk = ly6_h2_nsp_notrk->GetBinContent(ly6_ieta,ly6_iphi);
764 float ly6_frac = ( ly6_nsp > 0 ) ? ly6_nsp_notrk / ly6_nsp : 0;
765 if( ly6_nsp < 10 || ly6_frac < 0.85 ) continue;
766
767 float ly7_frac_max = 0;
768 float ly7_eta_max = 0;
769 float ly7_phi_max = 0;
770 for(int ly7_ieta=std::max(1,ly6_ieta-1); ly7_ieta<std::min(NBINS_ETA,ly6_ieta+1); ly7_ieta++) {
771 for(int ly7_iphi=std::max(1,ly6_iphi-1); ly7_iphi<=std::min(NBINS_PHI,ly6_iphi+1); ly7_iphi++) {
772 float ly7_nsp = ly7_h2_nsp ->GetBinContent(ly7_ieta,ly7_iphi);
773 float ly7_nsp_notrk = ly7_h2_nsp_notrk->GetBinContent(ly7_ieta,ly7_iphi);
774 float ly7_frac = ( ly7_nsp > 0 ) ? ly7_nsp_notrk / ly7_nsp : 0;
775 if( ly7_nsp < 10 ) continue;
776 if( ly7_frac > ly7_frac_max ) {
777 ly7_frac_max = ly7_frac;
778 ly7_eta_max = (ly7_h2_nsp->GetXaxis()->GetBinLowEdge(ly7_ieta) + ly7_h2_nsp->GetXaxis()->GetBinUpEdge(ly7_ieta))/2.0;
779 ly7_phi_max = (ly7_h2_nsp->GetXaxis()->GetBinLowEdge(ly7_iphi) + ly7_h2_nsp->GetXaxis()->GetBinUpEdge(ly7_iphi))/2.0;
780 }
781 }
782 }
783 if( ly7_frac_max < 0.85 ) continue;
784 //
785 float wsum = ly6_frac + ly7_frac_max;
786 float weta = (ly6_eta*ly6_frac + ly7_eta_max*ly7_frac_max) / wsum;
787 float wphi = (ly6_phi*ly6_frac + ly7_phi_max*ly7_frac_max) / wsum;
788 float w = wsum / 2.0;
789 QT.push_back(std::make_tuple(-1,w,weta,wphi));
790 }
791 }
792 ATH_MSG_VERBOSE("nr of ly6/ly7 doublet candidate seeds=" << QT.size() << ", doing clustering...");
793
794 // sort
795 std::sort(QT.begin(), QT.end(),
796 [](const std::tuple<int,float,float,float>& lhs, const std::tuple<int,float,float,float>& rhs) {
797 return std::get<1>(lhs) > std::get<1>(rhs); } );
798
799 // clustering
800 const double CLUSTCUT_DIST_SQUARED = 0.04; // const double CLUSTCUT_DIST = 0.2;
801 const double CLUSTCUT_SEED_FRAC = 0.9;
802
803 std::vector<float> seeds_wsum;
804
805 for(unsigned int i=0; i<QT.size(); i++) {
806 float phi = std::get<3>(QT[i]);
807 float eta = std::get<2>(QT[i]);
808 float w = std::get<1>(QT[i]);
809 if(i==0) {
810 seeds_eta.push_back(w*eta); seeds_phi.push_back(w*phi);
811 seeds_wsum.push_back(w);
812 continue;
813 }
814 const int IDX_INITIAL = 100;
815 float dist2_min = 100.0;
816 int idx_min = IDX_INITIAL;
817 for(unsigned j=0; j<seeds_eta.size(); j++) {
818 float ceta = seeds_eta[j]/seeds_wsum[j];
819 float cphi = seeds_phi[j]/seeds_wsum[j];
820 // intentionally calculate in this way as phi is defined beyond -Pi/Pi (no boundary)
821 float deta = std::fabs(ceta-eta);
822 float dphi = std::fabs(cphi-phi);
823 float dist2 = dphi*dphi+deta*deta;
824 if( dist2 < dist2_min ) {
825 dist2_min = dist2;
826 idx_min = j;
827 }
828 }
829 int match_idx = IDX_INITIAL;
830 if( idx_min != IDX_INITIAL ) {
831 if( dist2_min < CLUSTCUT_DIST_SQUARED ) { match_idx = idx_min; }
832 }
833 if( match_idx == IDX_INITIAL ) {
834 if( w > CLUSTCUT_SEED_FRAC && dist2_min > CLUSTCUT_DIST_SQUARED ) {
835 seeds_eta.push_back(w*eta); seeds_phi.push_back(w*phi);
836 seeds_wsum.push_back(w);
837 }
838 continue;
839 }
840 float new_eta = seeds_eta[match_idx] + w*eta;
841 float new_phi = seeds_phi[match_idx] + w*phi;
842 float new_wsum = seeds_wsum[match_idx] + w;
843 seeds_eta[match_idx] = new_eta;
844 seeds_phi[match_idx] = new_phi;
845 seeds_wsum[match_idx] = new_wsum;
846 }
847 QT.clear();
848 for(unsigned int i=0; i<seeds_eta.size(); i++) {
849 float eta = seeds_eta[i] / seeds_wsum[i];
850 float phi = seeds_phi[i] / seeds_wsum[i];
851 seeds_eta[i] = eta;
852 seeds_phi[i] = phi;
853 if( phi < -TMath::Pi() ) phi = 2*TMath::Pi() + phi;
854 if( phi > TMath::Pi() ) phi = -2*TMath::Pi() + phi;
855 seeds_phi[i] = phi;
856 }
857 ATH_MSG_VERBOSE("after clustering, nr of seeds = " << seeds_eta.size());
858
859 // delete overlap (can happen at phi=-Pi/Pi bounadry)
860 std::vector<unsigned int> idx_to_delete;
861 for(unsigned int i=0; i<seeds_eta.size(); i++) {
862 if( std::find(idx_to_delete.begin(),idx_to_delete.end(),i) != idx_to_delete.end() ) continue;
863 float eta_i = seeds_eta[i];
864 float phi_i = seeds_phi[i];
865 for(unsigned int j=i+1; j<seeds_eta.size(); j++) {
866 if( std::find(idx_to_delete.begin(),idx_to_delete.end(),j) != idx_to_delete.end() ) continue;
867 float eta_j = seeds_eta[j];
868 float phi_j = seeds_phi[j];
869 float dR2 = deltaR2(eta_i,phi_i,eta_j,phi_j);
870 if( dR2 < CLUSTCUT_DIST_SQUARED ) idx_to_delete.push_back(j);
871 }
872 }
873 ATH_MSG_VERBOSE("nr of duplicated seeds to be removed = " << idx_to_delete.size());
874 if( idx_to_delete.size() > 0 ) {
875 std::sort(idx_to_delete.begin(),idx_to_delete.end());
876 for(unsigned int j=idx_to_delete.size(); j>0; j--) {
877 unsigned int idx = idx_to_delete[j-1];
878 seeds_eta.erase(seeds_eta.begin()+idx);
879 seeds_phi.erase(seeds_phi.begin()+idx);
880 }
881 }
882
883 ATH_MSG_VERBOSE("nr of ly6/ly7 seeds=" << seeds_eta.size());
884
885 // return
886 return StatusCode::SUCCESS;
887}
888
889// ------------------------------------------------------------------------------------------------
890// ------------------------------------------------------------------------------------------------
891
892StatusCode TrigHitDVHypoAlg::selectSeedsNearby(const std::vector<HitDVSeed>& hitDVSeedsContainer,
893 std::vector<float>& jetSeeds_eta, std::vector<float>& jetSeeds_phi, std::vector<float>& jetSeeds_pt) const
894{
895 std::vector<unsigned int> idx_to_delete;
896 for(unsigned int idx=0; idx<jetSeeds_eta.size(); ++idx) {
897 const float DR_SQUARED_CUT_TO_FTFSEED = 0.09; // const float DR_CUT_TO_FTFSEED = 0.3;
898 float eta = jetSeeds_eta[idx];
899 float phi = jetSeeds_phi[idx];
900 float dR2min = 9999;
901 for ( const auto& seed : hitDVSeedsContainer ) {
902 float dR2 = deltaR2(eta,phi,seed.eta,seed.phi);
903 if( dR2 < dR2min ) dR2min = dR2;
904 }
905 if( dR2min > DR_SQUARED_CUT_TO_FTFSEED ) idx_to_delete.push_back(idx);
906 }
907 if( idx_to_delete.size() > 0 ) {
908 std::sort(idx_to_delete.begin(),idx_to_delete.end());
909 for(unsigned int j=idx_to_delete.size(); j>0; j--) {
910 unsigned int idx = idx_to_delete[j-1];
911 jetSeeds_eta.erase(jetSeeds_eta.begin()+idx);
912 jetSeeds_phi.erase(jetSeeds_phi.begin()+idx);
913 if( jetSeeds_pt.size() > 0 ) jetSeeds_pt.erase(jetSeeds_pt.begin()+idx);
914 }
915 }
916 return StatusCode::SUCCESS;
917}
918
919// ------------------------------------------------------------------------------------------------
920// ------------------------------------------------------------------------------------------------
921
922StatusCode TrigHitDVHypoAlg::findSPSeeds( const EventContext& ctx,
923 const std::vector<float>& v_sp_eta, const std::vector<float>& v_sp_phi,
924 const std::vector<int>& v_sp_layer, const std::vector<int>& v_sp_usedTrkId,
925 std::vector<float>& seeds_eta, std::vector<float>& seeds_phi ) const
926{
927 const int NBINS_ETA = 50;
928 const float ETA_MIN = -2.5;
929 const float ETA_MAX = 2.5;
930
931 const int NBINS_PHI = 80;
932 const float PHI_MIN = -4.0;
933 const float PHI_MAX = 4.0;
934
935 char hname[64];
936
937 unsigned int slotnr = ctx.slot();
938 unsigned int subSlotnr = ctx.subSlot();
939
940 sprintf(hname,"ftf_s%u_ss%u_ly6_h2_nsp",slotnr,subSlotnr);
941 std::unique_ptr<TH2F> ly6_h2_nsp = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
942 sprintf(hname,"ftf_s%u_ss%u_ly7_h2_nsp",slotnr,subSlotnr);
943 std::unique_ptr<TH2F> ly7_h2_nsp = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
944
945 sprintf(hname,"ftf_s%u_ss%u_ly6_h2_nsp_notrk",slotnr,subSlotnr);
946 std::unique_ptr<TH2F> ly6_h2_nsp_notrk = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
947 sprintf(hname,"ftf_s%u_ss%u_ly7_h2_nsp_notrk",slotnr,subSlotnr);
948 std::unique_ptr<TH2F> ly7_h2_nsp_notrk = std::make_unique<TH2F>(hname,hname,NBINS_ETA,ETA_MIN,ETA_MAX,NBINS_PHI,PHI_MIN,PHI_MAX);
949
950 for(unsigned int iSeed=0; iSeed<v_sp_eta.size(); ++iSeed) {
951
952 int sp_layer = v_sp_layer[iSeed];
953 float sp_eta = v_sp_eta[iSeed];
954 int ilayer = getSPLayer(sp_layer,sp_eta);
955 if( ilayer<6 ) continue;
956
957 int sp_trkid = v_sp_usedTrkId[iSeed];
958 bool isUsedByTrk = (sp_trkid != -1);
959 float sp_phi = v_sp_phi[iSeed];
960
961 bool fill_out_of_pi = false;
962 float sp_phi2 = 0;
963 if( sp_phi < 0 ) {
964 sp_phi2 = 2*TMath::Pi() + sp_phi;
965 if( sp_phi2 < PHI_MAX ) fill_out_of_pi = true;
966 }
967 else {
968 sp_phi2 = -2*TMath::Pi() + sp_phi;
969 if( PHI_MIN < sp_phi2 ) fill_out_of_pi = true;
970 }
971 if( ilayer==6 ) {
972 ly6_h2_nsp->Fill(sp_eta,sp_phi);
973 if( fill_out_of_pi ) ly6_h2_nsp->Fill(sp_eta,sp_phi2);
974 if( ! isUsedByTrk ) ly6_h2_nsp_notrk->Fill(sp_eta,sp_phi);
975 if( ! isUsedByTrk && fill_out_of_pi) ly6_h2_nsp_notrk->Fill(sp_eta,sp_phi2);
976 }
977 if( ilayer==7 ) {
978 ly7_h2_nsp->Fill(sp_eta,sp_phi);
979 if( fill_out_of_pi ) ly7_h2_nsp->Fill(sp_eta,sp_phi2);
980 if( ! isUsedByTrk ) ly7_h2_nsp_notrk->Fill(sp_eta,sp_phi);
981 if( ! isUsedByTrk && fill_out_of_pi) ly7_h2_nsp_notrk->Fill(sp_eta,sp_phi2);
982 }
983 }
984
985 ATH_MSG_VERBOSE("looking for ly6/ly6 doublet seeds");
986
987 // (idx, sort/weight, eta, phi)
988 std::vector<std::tuple<int,float,float,float>> QT;
989
990 for(int ly6_ieta=1; ly6_ieta<=NBINS_ETA; ly6_ieta++) {
991 float ly6_eta = (ly6_h2_nsp->GetXaxis()->GetBinLowEdge(ly6_ieta) + ly6_h2_nsp->GetXaxis()->GetBinUpEdge(ly6_ieta))/2.0;
992 for(int ly6_iphi=1; ly6_iphi<=NBINS_PHI; ly6_iphi++) {
993 float ly6_phi = (ly6_h2_nsp->GetYaxis()->GetBinLowEdge(ly6_iphi) + ly6_h2_nsp->GetYaxis()->GetBinUpEdge(ly6_iphi))/2.0;
994
995 float ly6_nsp = ly6_h2_nsp ->GetBinContent(ly6_ieta,ly6_iphi);
996 float ly6_nsp_notrk = ly6_h2_nsp_notrk->GetBinContent(ly6_ieta,ly6_iphi);
997 float ly6_frac = ( ly6_nsp > 0 ) ? ly6_nsp_notrk / ly6_nsp : 0;
998 if( ly6_nsp < 10 || ly6_frac < 0.85 ) continue;
999
1000 float ly7_frac_max = 0;
1001 float ly7_eta_max = 0;
1002 float ly7_phi_max = 0;
1003 for(int ly7_ieta=std::max(1,ly6_ieta-1); ly7_ieta<std::min(NBINS_ETA,ly6_ieta+1); ly7_ieta++) {
1004 for(int ly7_iphi=std::max(1,ly6_iphi-1); ly7_iphi<=std::min(NBINS_PHI,ly6_iphi+1); ly7_iphi++) {
1005 float ly7_nsp = ly7_h2_nsp ->GetBinContent(ly7_ieta,ly7_iphi);
1006 float ly7_nsp_notrk = ly7_h2_nsp_notrk->GetBinContent(ly7_ieta,ly7_iphi);
1007 float ly7_frac = ( ly7_nsp > 0 ) ? ly7_nsp_notrk / ly7_nsp : 0;
1008 if( ly7_nsp < 10 ) continue;
1009 if( ly7_frac > ly7_frac_max ) {
1010 ly7_frac_max = ly7_frac;
1011 ly7_eta_max = (ly7_h2_nsp->GetXaxis()->GetBinLowEdge(ly7_ieta) + ly7_h2_nsp->GetXaxis()->GetBinUpEdge(ly7_ieta))/2.0;
1012 ly7_phi_max = (ly7_h2_nsp->GetXaxis()->GetBinLowEdge(ly7_iphi) + ly7_h2_nsp->GetXaxis()->GetBinUpEdge(ly7_iphi))/2.0;
1013 }
1014 }
1015 }
1016 if( ly7_frac_max < 0.85 ) continue;
1017 //
1018 float wsum = ly6_frac + ly7_frac_max;
1019 float weta = (ly6_eta*ly6_frac + ly7_eta_max*ly7_frac_max) / wsum;
1020 float wphi = (ly6_phi*ly6_frac + ly7_phi_max*ly7_frac_max) / wsum;
1021 float w = wsum / 2.0;
1022 QT.push_back(std::make_tuple(-1,w,weta,wphi));
1023 }
1024 }
1025 ATH_MSG_VERBOSE("nr of ly6/ly7 doublet candidate seeds=" << QT.size() << ", doing clustering...");
1026
1027 // sort
1028 std::sort(QT.begin(), QT.end(),
1029 [](const std::tuple<int,float,float,float>& lhs, const std::tuple<int,float,float,float>& rhs) {
1030 return std::get<1>(lhs) > std::get<1>(rhs); } );
1031
1032 // clustering
1033 const double CLUSTCUT_DIST_SQUARED = 0.04; // const double CLUSTCUT_DIST = 0.2;
1034 const double CLUSTCUT_SEED_FRAC = 0.9;
1035
1036 std::vector<float> seeds_wsum;
1037
1038 for(unsigned int i=0; i<QT.size(); i++) {
1039 float phi = std::get<3>(QT[i]);
1040 float eta = std::get<2>(QT[i]);
1041 float w = std::get<1>(QT[i]);
1042 if(i==0) {
1043 seeds_eta.push_back(w*eta); seeds_phi.push_back(w*phi);
1044 seeds_wsum.push_back(w);
1045 continue;
1046 }
1047 const int IDX_INITIAL = 100;
1048 float dist2_min = 100.0;
1049 int idx_min = IDX_INITIAL;
1050 for(unsigned j=0; j<seeds_eta.size(); j++) {
1051 float ceta = seeds_eta[j]/seeds_wsum[j];
1052 float cphi = seeds_phi[j]/seeds_wsum[j];
1053 // intentionally calculate in this way as phi is defined beyond -Pi/Pi (no boundary)
1054 float deta = std::fabs(ceta-eta);
1055 float dphi = std::fabs(cphi-phi);
1056 float dist2 = dphi*dphi+deta*deta;
1057 if( dist2 < dist2_min ) {
1058 dist2_min = dist2;
1059 idx_min = j;
1060 }
1061 }
1062 int match_idx = IDX_INITIAL;
1063 if( idx_min != IDX_INITIAL ) {
1064 if( dist2_min < CLUSTCUT_DIST_SQUARED ) { match_idx = idx_min; }
1065 }
1066 if( match_idx == IDX_INITIAL ) {
1067 if( w > CLUSTCUT_SEED_FRAC && dist2_min > CLUSTCUT_DIST_SQUARED ) {
1068 seeds_eta.push_back(w*eta); seeds_phi.push_back(w*phi);
1069 seeds_wsum.push_back(w);
1070 }
1071 continue;
1072 }
1073 float new_eta = seeds_eta[match_idx] + w*eta;
1074 float new_phi = seeds_phi[match_idx] + w*phi;
1075 float new_wsum = seeds_wsum[match_idx] + w;
1076 seeds_eta[match_idx] = new_eta;
1077 seeds_phi[match_idx] = new_phi;
1078 seeds_wsum[match_idx] = new_wsum;
1079 }
1080 QT.clear();
1081 for(unsigned int i=0; i<seeds_eta.size(); i++) {
1082 float eta = seeds_eta[i] / seeds_wsum[i];
1083 float phi = seeds_phi[i] / seeds_wsum[i];
1084 seeds_eta[i] = eta;
1085 if( phi < -TMath::Pi() ) phi = 2*TMath::Pi() + phi;
1086 if( phi > TMath::Pi() ) phi = -2*TMath::Pi() + phi;
1087 seeds_phi[i] = phi;
1088 }
1089 ATH_MSG_VERBOSE("after clustering, nr of seeds = " << seeds_eta.size());
1090
1091 // delete overlap (can happen at phi=-Pi/Pi bounadry)
1092 std::vector<unsigned int> idx_to_delete;
1093 for(unsigned int i=0; i<seeds_eta.size(); i++) {
1094 if( std::find(idx_to_delete.begin(),idx_to_delete.end(),i) != idx_to_delete.end() ) continue;
1095 float eta_i = seeds_eta[i];
1096 float phi_i = seeds_phi[i];
1097 for(unsigned int j=i+1; j<seeds_eta.size(); j++) {
1098 if( std::find(idx_to_delete.begin(),idx_to_delete.end(),j) != idx_to_delete.end() ) continue;
1099 float eta_j = seeds_eta[j];
1100 float phi_j = seeds_phi[j];
1101 float dR2 = deltaR2(eta_i,phi_i,eta_j,phi_j);
1102 if( dR2 < CLUSTCUT_DIST_SQUARED ) idx_to_delete.push_back(j);
1103 }
1104 }
1105 ATH_MSG_VERBOSE("nr of duplicated seeds to be removed = " << idx_to_delete.size());
1106 if( idx_to_delete.size() > 0 ) {
1107 std::sort(idx_to_delete.begin(),idx_to_delete.end());
1108 for(unsigned int j=idx_to_delete.size(); j>0; j--) {
1109 unsigned int idx = idx_to_delete[j-1];
1110 seeds_eta.erase(seeds_eta.begin()+idx);
1111 seeds_phi.erase(seeds_phi.begin()+idx);
1112 }
1113 }
1114
1115 ATH_MSG_VERBOSE("nr of ly6/ly7 seeds=" << seeds_eta.size());
1116
1117 // return
1118 return StatusCode::SUCCESS;
1119}
1120
1121StatusCode TrigHitDVHypoAlg::findHitDV(const EventContext& ctx, const std::vector<TrigSiSpacePointBase>& convertedSpacePoints,
1122 const DataVector<Trk::Track>& tracks, std::vector<HitDVSeed>& hitDVSeedsContainer,
1123 std::vector<HitDVTrk>& hitDVTrksContainer,
1124 std::vector<HitDVSpacePoint>& hitDVSPsContainer) const
1125{
1126 std::vector<int> v_dvtrk_id;
1127 std::vector<float> v_dvtrk_pt;
1128 std::vector<float> v_dvtrk_eta;
1129 std::vector<float> v_dvtrk_phi;
1130 std::vector<int> v_dvtrk_n_hits_inner;
1131 std::vector<int> v_dvtrk_n_hits_pix;
1132 std::vector<int> v_dvtrk_n_hits_sct;
1133 std::vector<float> v_dvtrk_a0beam;
1134 std::unordered_map<Identifier, int> umap_fittedTrack_identifier;
1135 int fittedTrack_id = -1;
1136
1137 static constexpr float TRKCUT_PTGEV_HITDV = 0.5;
1138
1139 for (const auto track: tracks) {
1140 float shift_x = 0; float shift_y = 0;
1141 if(m_useBeamSpot) {
1143 FTF::getBeamSpotShift(shift_x, shift_y, **beamSpotHandle);
1144 }
1145 trackInfo theTrackInfo;
1146 bool igt = FTF::isGoodTrackUTT(track, theTrackInfo, shift_x, shift_y, TRKCUT_PTGEV_HITDV);
1147 if (not igt) {continue;}
1148
1149 fittedTrack_id++;
1150 ATH_MSG_DEBUG("Selected track pT = " << theTrackInfo.ptGeV << " GeV");
1151
1152
1154 m = track->measurementsOnTrack()->begin(),
1155 me = track->measurementsOnTrack()->end ();
1156 for(; m!=me; ++m ) {
1157 const Trk::PrepRawData* prd = ((const Trk::RIO_OnTrack*)(*m))->prepRawData();
1158 if( prd == nullptr ) continue;
1159 Identifier id_prd = prd->identify();
1160 if( umap_fittedTrack_identifier.find(id_prd) == umap_fittedTrack_identifier.end() ) {
1161 umap_fittedTrack_identifier.insert(std::make_pair(id_prd,fittedTrack_id));
1162 }
1163 }
1164 float phi = track->perigeeParameters()->parameters()[Trk::phi];
1165 v_dvtrk_id.push_back(fittedTrack_id);
1166 v_dvtrk_pt.push_back(theTrackInfo.ptGeV*Gaudi::Units::GeV);
1167 v_dvtrk_eta.push_back(theTrackInfo.eta);
1168 v_dvtrk_phi.push_back(phi);
1169 v_dvtrk_n_hits_inner.push_back(theTrackInfo.n_hits_inner);
1170 v_dvtrk_n_hits_pix.push_back(theTrackInfo.n_hits_pix);
1171 v_dvtrk_n_hits_sct.push_back(theTrackInfo.n_hits_sct);
1172 v_dvtrk_a0beam.push_back(theTrackInfo.a0beam);
1173 }
1174 ATH_MSG_DEBUG("Nr of selected tracks / all = " << fittedTrack_id << " / " << tracks.size());
1175 ATH_MSG_DEBUG("Nr of Identifiers used by selected tracks = " << umap_fittedTrack_identifier.size());
1176
1177 // space points
1178 int n_sp = 0;
1179 int n_sp_usedByTrk = 0;
1180
1181 std::unordered_map<Identifier, int> umap_sp_identifier;
1182 umap_sp_identifier.reserve(1.3*convertedSpacePoints.size());//up to 2 Identifiers per spacepoint, end up with 1.3 from measurements
1183
1184 auto add_to_sp_map = [&](const Trk::PrepRawData* prd) {
1185 if (prd) {
1186 Identifier id_prd = prd->identify();
1187 if( umap_sp_identifier.find(id_prd) == umap_sp_identifier.end() ) {
1188 umap_sp_identifier.insert(std::make_pair(id_prd,-1));
1189 }
1190 }
1191 };
1192
1193 for(unsigned int iSp=0; iSp<convertedSpacePoints.size(); ++iSp) {
1194 bool isPix = convertedSpacePoints[iSp].isPixel();
1195 bool isSct = convertedSpacePoints[iSp].isSCT();
1196 if( ! isPix && ! isSct ) continue;
1197 const Trk::SpacePoint* sp = convertedSpacePoints[iSp].offlineSpacePoint();
1198 add_to_sp_map(sp->clusterList().first);
1199 add_to_sp_map(sp->clusterList().second);
1200 }
1201 int n_id_usedByTrack = 0;
1202 for(auto it=umap_sp_identifier.begin(); it!=umap_sp_identifier.end(); ++it) {
1203 Identifier id_sp = it->first;
1204 if( umap_fittedTrack_identifier.find(id_sp) != umap_fittedTrack_identifier.end() ) {
1205 umap_sp_identifier[id_sp] = umap_fittedTrack_identifier[id_sp];
1206 ++n_id_usedByTrack;
1207 }
1208 }
1209 ATH_MSG_DEBUG("Nr of SPs / Identifiers (all) / Identifiers (usedByTrack) = " << convertedSpacePoints.size() << " / " << umap_sp_identifier.size() << " / " << n_id_usedByTrack);
1210
1211 auto sp_map_used_id = [&](const Trk::PrepRawData* prd) {
1212 int usedTrack_id = -1;
1213 if (prd) {
1214 Identifier id_prd = prd->identify();
1215 if( umap_sp_identifier.find(id_prd) != umap_sp_identifier.end() ) {
1216 usedTrack_id = umap_sp_identifier[id_prd];
1217 }
1218 }
1219 return usedTrack_id;
1220 };
1221
1222 std::vector<float> v_sp_eta;
1223 v_sp_eta.reserve(convertedSpacePoints.size());
1224 std::vector<float> v_sp_r;
1225 v_sp_r.reserve(convertedSpacePoints.size());
1226 std::vector<float> v_sp_phi;
1227 v_sp_phi.reserve(convertedSpacePoints.size());
1228 std::vector<int> v_sp_layer;
1229 v_sp_layer.reserve(convertedSpacePoints.size());
1230 std::vector<bool> v_sp_isPix;
1231 v_sp_isPix.reserve(convertedSpacePoints.size());
1232 std::vector<bool> v_sp_isSct;
1233 v_sp_isSct.reserve(convertedSpacePoints.size());
1234 std::vector<int> v_sp_usedTrkId;
1235 v_sp_usedTrkId.reserve(convertedSpacePoints.size());
1236
1237 for(const auto& sp : convertedSpacePoints) {
1238 bool isPix = sp.isPixel();
1239 bool isSct = sp.isSCT();
1240 if( ! isPix && ! isSct ) continue;
1241 const Trk::SpacePoint* osp = sp.offlineSpacePoint();
1242
1243 int usedTrack_id = -1;
1244 int usedTrack_id_first = sp_map_used_id(osp->clusterList().first);
1245 if (usedTrack_id_first != -1) {
1246 usedTrack_id = usedTrack_id_first;
1247 }
1248 int usedTrack_id_second = sp_map_used_id(osp->clusterList().second);
1249 if (usedTrack_id_second != -1) {
1250 usedTrack_id = usedTrack_id_second;
1251 }
1252
1253 //
1254 n_sp++;
1255 if( usedTrack_id != -1 ) n_sp_usedByTrk++;
1256 int layer = sp.layer();
1257 float sp_r = sp.r();
1258
1259 const Amg::Vector3D& pos_sp = osp->globalPosition();//Go back to globalPosition to get the non-shifted spacepoint positions
1260 float sp_eta = pos_sp.eta();
1261 float sp_phi = pos_sp.phi();
1262
1263 v_sp_eta.push_back(sp_eta);
1264 v_sp_r.push_back(sp_r);
1265 v_sp_phi.push_back(sp_phi);
1266 v_sp_layer.push_back(layer);
1267 v_sp_isPix.push_back(isPix);
1268 v_sp_isSct.push_back(isSct);
1269 v_sp_usedTrkId.push_back(usedTrack_id);
1270
1271 ATH_MSG_VERBOSE("+++ SP eta / phi / layer / ixPix / usedTrack_id = " << sp_eta << " / " << sp_phi << " / " << layer << " / " << isPix << " / " << usedTrack_id);
1272
1273 }
1274 ATH_MSG_DEBUG("Nr of SPs / all = " << n_sp << " / " << convertedSpacePoints.size());
1275 ATH_MSG_DEBUG("Nr of SPs used by selected tracks = " << n_sp_usedByTrk);
1276
1277 // Seed
1278 std::vector<float> v_seeds_eta;
1279 std::vector<float> v_seeds_phi;
1280 std::vector<int16_t> v_seeds_type;
1281
1282 if( m_doHitDV_Seeding ) {
1283
1284 // add L1 Jet seeds
1285 const unsigned int L1JET_ET_CUT = 27; // Mapping from legacy J30, make configurable?
1286
1287 auto jetRoiCollectionHandle = SG::makeHandle( m_jetRoiCollectionKey, ctx );
1288 const DataVector<xAOD::jFexSRJetRoI> *jetRoiCollection = jetRoiCollectionHandle.cptr();
1289 if (!jetRoiCollectionHandle.isValid()){
1290 ATH_MSG_ERROR("ReadHandle for DataVector<xAOD::jFexSRJetRoI> key:" << m_jetRoiCollectionKey.key() << " isn't Valid");
1291 return StatusCode::FAILURE;
1292 }
1293 for (size_t size=0; size<jetRoiCollection->size(); ++size){
1294 const xAOD::jFexSRJetRoI* jetRoI = jetRoiCollection->at(size);
1295 if( jetRoI == nullptr ) continue;
1296 // Good seed
1297 if( jetRoI->et() >= L1JET_ET_CUT ) {
1298 v_seeds_eta.push_back(jetRoI->eta());
1299 v_seeds_phi.push_back(jetRoI->phi());
1300 v_seeds_type.push_back(0); // L1_J:0
1301 }
1302 }
1303 ATH_MSG_DEBUG("Nr of L1_J" << L1JET_ET_CUT << " seeds = " << v_seeds_eta.size());
1304
1305 // space-point based (unseeded mode)
1306 std::vector<float> v_spseeds_eta;
1307 std::vector<float> v_spseeds_phi;
1308 ATH_CHECK( findSPSeeds(ctx, v_sp_eta, v_sp_phi, v_sp_layer, v_sp_usedTrkId, v_spseeds_eta, v_spseeds_phi) );
1309 ATH_MSG_DEBUG("Nr of SP seeds = " << v_spseeds_eta.size());
1310 for(size_t idx=0; idx<v_spseeds_eta.size(); ++idx) {
1311 v_seeds_eta.push_back(v_spseeds_eta[idx]);
1312 v_seeds_phi.push_back(v_spseeds_phi[idx]);
1313 v_seeds_type.push_back(1); // SP: 1
1314 }
1315 ATH_MSG_DEBUG("Nr of SP + L1_J" << L1JET_ET_CUT << " seeds = " << v_seeds_eta.size());
1316 }
1317
1318 // fill objects
1319
1320 // seeds
1321 const int N_MAX_SEEDS = 200;
1322 int n_seeds = std::min(N_MAX_SEEDS,(int)v_seeds_eta.size());
1323 hitDVSeedsContainer.reserve(n_seeds);
1324 for(auto iSeed=0; iSeed < n_seeds; ++iSeed) {
1325 HitDVSeed seed;
1326 seed.eta = v_seeds_eta[iSeed];
1327 seed.phi = v_seeds_phi[iSeed];
1328 seed.type = v_seeds_type[iSeed];
1329 hitDVSeedsContainer.push_back(seed);
1330 }
1331
1332 // track
1333 const float TRKCUT_DELTA_R_TO_SEED = 1.0;
1334 hitDVTrksContainer.reserve(v_dvtrk_pt.size());
1335 for(unsigned int iTrk=0; iTrk<v_dvtrk_pt.size(); ++iTrk) {
1336 float trk_eta = v_dvtrk_eta[iTrk];
1337 float trk_phi = v_dvtrk_phi[iTrk];
1338 if( m_doHitDV_Seeding ) {
1339 bool isNearSeed = false;
1340 for (unsigned int iSeed=0; iSeed<v_seeds_eta.size(); ++iSeed) {
1341 float seed_eta = v_seeds_eta[iSeed];
1342 float seed_phi = v_seeds_phi[iSeed];
1343 float dR2 = deltaR2(trk_eta,trk_phi,seed_eta,seed_phi);
1344 if( dR2 <= TRKCUT_DELTA_R_TO_SEED*TRKCUT_DELTA_R_TO_SEED ) { isNearSeed = true; break; }
1345 }
1346 if( ! isNearSeed ) continue;
1347 }
1348 HitDVTrk hitDVTrk;
1349 hitDVTrk.id = v_dvtrk_id[iTrk];
1350 hitDVTrk.pt = v_dvtrk_pt[iTrk];
1351 hitDVTrk.eta = v_dvtrk_eta[iTrk];
1352 hitDVTrk.phi = v_dvtrk_phi[iTrk];
1353 hitDVTrk.n_hits_inner = v_dvtrk_n_hits_inner[iTrk];
1354 hitDVTrk.n_hits_pix = v_dvtrk_n_hits_pix[iTrk];
1355 hitDVTrk.n_hits_sct = v_dvtrk_n_hits_sct[iTrk];
1356 hitDVTrk.a0beam = v_dvtrk_a0beam[iTrk];
1357
1358 hitDVTrksContainer.push_back(hitDVTrk);
1359 }
1360
1361 // space points
1362 const float SPCUT_DELTA_R_TO_SEED = 1.0;
1363 const size_t n_sp_max = std::min<size_t>(100000, v_sp_eta.size());
1364 size_t n_sp_stored = 0;
1365
1366 hitDVSPsContainer.reserve(n_sp_max);
1367
1368 for(size_t iSp=0; iSp<v_sp_eta.size(); ++iSp) {
1369 if( m_doHitDV_Seeding ) {
1370 const float sp_eta = v_sp_eta[iSp];
1371 const float sp_phi = v_sp_phi[iSp];
1372 bool isNearSeed = false;
1373 for (size_t iSeed=0; iSeed<v_seeds_eta.size(); ++iSeed) {
1374 const float seed_eta = v_seeds_eta[iSeed];
1375 const float seed_phi = v_seeds_phi[iSeed];
1376 const float dR2 = deltaR2(sp_eta, sp_phi, seed_eta, seed_phi);
1377 if( dR2 <= SPCUT_DELTA_R_TO_SEED*SPCUT_DELTA_R_TO_SEED ) { isNearSeed = true; break; }
1378 }
1379 if( ! isNearSeed ) continue;
1380 }
1381 if( n_sp_stored >= n_sp_max ) break;
1382 HitDVSpacePoint hitDVSP;
1383 hitDVSP.eta = v_sp_eta[iSp];
1384 hitDVSP.r = v_sp_r[iSp];
1385 hitDVSP.phi = v_sp_phi[iSp];
1386 hitDVSP.layer = v_sp_layer[iSp];
1387 hitDVSP.isPix = v_sp_isPix[iSp];
1388 hitDVSP.isSct = v_sp_isSct[iSp];
1389 hitDVSP.usedTrkId = v_sp_usedTrkId[iSp];
1390 hitDVSPsContainer.push_back(hitDVSP);
1391 ++n_sp_stored;
1392 }
1393 ATH_MSG_DEBUG("Nr of SPs stored = " << n_sp_stored);
1394
1395 return StatusCode::SUCCESS;
1396}
#define M_PI
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define CHECK(...)
Evaluate an expression and check for errors.
static Double_t sp
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
const std::string & featureString()
Header file to be included by clients of the Monitored infrastructure.
bool allFailed(const Decision *d)
return true if there is no positive decision stored
size_t size() const
Number of registered mappings.
Athena::TPCnvVers::Current TrigRoiDescriptor
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Standard const_iterator.
Definition DataVector.h:838
const T * at(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
size_type size() const noexcept
Returns the number of elements in the collection.
const SG::ReadHandleKey< TrigCompositeUtils::DecisionContainer > & decisionInput() const
methods for derived classes to access handles of the base class input other read/write handles may be...
Definition HypoBase.cxx:18
const SG::WriteHandleKey< TrigCompositeUtils::DecisionContainer > & decisionOutput() const
methods for derived classes to access handles of the base class output other read/write handles may b...
Definition HypoBase.cxx:22
StatusCode hypoBaseOutputProcessing(SG::WriteHandle< TrigCompositeUtils::DecisionContainer > &outputHandle, MSG::Level lvl=MSG::DEBUG) const
Base class function to be called once slice specific code has finished. Handles debug printing and va...
Definition HypoBase.cxx:35
HypoBase(const std::string &name, ISvcLocator *pSvcLocator)
constructor, to be called by sub-class constructors
Definition HypoBase.cxx:12
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
static std::string find_calib_file(const std::string &logical_file_name)
const_pointer_type cptr()
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
pointer_type ptr()
Dereference the pointer.
float deltaR2(float, float, float, float) const
ToolHandleArray< TrigHitDVHypoTool > m_hypoTools
ToolHandle< GenericMonitoringTool > m_monTool
TrigHitDVHypoAlg(const std::string &name, ISvcLocator *pSvcLocator)
StatusCode findHitDV(const EventContext &ctx, const std::vector< TrigSiSpacePointBase > &convertedSpacePoints, const DataVector< Trk::Track > &tracks, std::vector< HitDVSeed > &hitDVSeedsContainer, std::vector< HitDVTrk > &hitDVTrksContainer, std::vector< HitDVSpacePoint > &hitDVSPContainer) const
SG::ReadCondHandleKey< LuminosityCondData > m_lumiDataKey
Gaudi::Property< float > m_jetSeed_ptMin
virtual StatusCode execute(const EventContext &context) const override
StatusCode calculateBDT(const std::vector< HitDVSpacePoint > &, const std::vector< HitDVTrk > &, const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, const float &, const int, xAOD::TrigCompositeContainer *, int &) const
int getSPLayer(int, float) const
SG::ReadHandleKey< xAOD::jFexSRJetRoIContainer > m_jetRoiCollectionKey
SG::ReadHandleKey< TrackCollection > m_tracksKey
Gaudi::Property< float > m_jetSeed_etaMax
ToolHandle< ITrigSpacePointConversionTool > m_spacePointTool
StatusCode selectSeedsNearby(const std::vector< HitDVSeed > &hitDVSeedsContainer, std::vector< float > &jetSeeds_eta, std::vector< float > &jetSeeds_phi, std::vector< float > &jetSeeds_pt) const
Gaudi::Property< bool > m_isMC
StatusCode findJetSeeds(const xAOD::JetContainer *, const float, const float, std::vector< float > &, std::vector< float > &, std::vector< float > &) const
ToolHandle< ILumiBlockMuTool > m_lumiBlockMuTool
StatusCode findSPSeeds(const EventContext &, const std::vector< HitDVSpacePoint > &, std::vector< float > &, std::vector< float > &) const
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
virtual StatusCode initialize() override
SG::WriteHandleKey< xAOD::TrigCompositeContainer > m_hitDVKey
SG::ReadHandleKey< xAOD::JetContainer > m_jetsKey
StatusCode doMonitor(const xAOD::TrigCompositeContainer *) const
std::unique_ptr< MVAUtils::BDT > m_bdt_eta[2]
nope - should be used for standalone also, perhaps need to protect the class def bits ifndef XAOD_ANA...
Identifier identify() const
return the identifier
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
const std::pair< const PrepRawData *, const PrepRawData * > & clusterList() const
return the pair of cluster pointers by reference
virtual const Amg::Vector3D & globalPosition() const override final
Interface method to get the global Position.
unsigned int et() const
Methods that require combining results or applying scales.
std::string base
Definition hcg.cxx:83
Eigen::Matrix< double, 3, 1 > Vector3D
constexpr T wrapToPi(T phi)
Wrap angle in radians to [-pi, pi].
Definition phihelper.h:31
void getBeamSpotShift(float &shift_x, float &shift_y, const InDet::BeamSpotData &beamSpotHandle)
bool isGoodTrackUTT(const Trk::Track *track, trackInfo &theTrackInfo, const float shift_x, const float shift_y, float trkcut_ptgev)
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
const std::string & viewString()
xAOD::TrigComposite Decision
Decision * newDecisionIn(DecisionContainer *dc, const std::string &name)
Helper method to create a Decision object, place it in the container and return a pointer to it.
const std::string & featureString()
xAOD::TrigCompositeAuxContainer DecisionAuxContainer
std::set< DecisionID > DecisionIDContainer
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
const std::string & hypoAlgNodeName()
void linkToPrevious(Decision *d, const std::string &previousCollectionKey, size_t previousIndex)
Links to the previous object, location of previous 'seed' decision supplied by hand.
LinkInfo< T > findLink(const EventContext &ctx, const Decision *start, const std::string &linkName, const bool suppressMultipleLinksWarning=false)
Perform a recursive search for ElementLinks of type T and name 'linkName', starting from Decision obj...
bool allFailed(const Decision *d)
return true if there is no positive decision stored
xAOD::TrigCompositeContainer DecisionContainer
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
@ phi
Definition ParamDefs.h:75
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Jet_v1 Jet
Definition of the current "jet version".
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
TrigComposite_v1 TrigComposite
Declare the latest version of the class.
JetContainer_v1 JetContainer
Definition of the current "jet container version".
jFexSRJetRoI_v1 jFexSRJetRoI
Define the latest version of the jFexSRJetRoI class.
Helper for azimuthal angle calculations.
int16_t n_hits_inner
int16_t n_hits_sct
int16_t n_hits_pix
Helper to keep a Decision object, ElementLink and ActiveState (with respect to some requested ChainGr...
Definition LinkInfo.h:22
TChain * tree