ATLAS Offline Software
Loading...
Searching...
No Matches
InDetDenseEnvAmbiTrackSelectionTool.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// InDetDenseEnvAmbiTrackSelectionTool.cxx, (c) ATLAS Detector software
7// Anthony Morley based on the orginal tool by Markus Elsing
8// Oct 2020 - Clean-up for rel22 - Gabriel Facini
10
12
23#include "TrkSurfaces/Surface.h"
24#include "TrkTrack/TrackInfo.h"
28
29#include "TString.h"
30
31//================ Constructor =================================================
32
34 const std::string& n,
35 const IInterface* p )
36:
37base_class(t,n,p){}
38
39//================ Initialisation =================================================
40
42{
43 ATH_CHECK(AlgTool::initialize());
44
45 // Get segment selector tool
46 ATH_CHECK(m_selectortool.retrieve(DisableTool{!m_parameterization}));
47
48 ATH_CHECK(detStore()->retrieve(m_detID, "SiliconID"));
49
50 if(!m_etaDependentCutsSvc.name().empty()) ATH_CHECK(m_etaDependentCutsSvc.retrieve());
51
52 ATH_CHECK(m_assoTool.retrieve());
53
54 ATH_CHECK(m_observerTool.retrieve(DisableTool{m_observerTool.empty()}));
55
58
59 return StatusCode::SUCCESS;
60}
61
63 return StatusCode::SUCCESS;
64}
65
66
67// @TODO move cluster "map" creation to separate algorithm
71
72
73//============================================================================================
75 const Trk::TrackScore score,
76 Trk::ClusterSplitProbabilityContainer &splitProbContainer,
77 Trk::PRDtoTrackMap &prd_to_track_map,
78 int trackId,
79 int subtrackId) const
80{
81
82 CacheEntry cache;
83
84 if (m_skipAmbiInROI && inHadronicROI(ptrTrack)){
85 ATH_MSG_DEBUG("skipping ambiguity resolution for track in hadronic ROI with m_minPtBjetROI = "<<m_minPtBjetROI<<", m_phiWidth = "<<m_phiWidth<<", m_etaWidth = "<<m_etaWidth);
86 return std::make_tuple(static_cast<Trk::Track *>(nullptr),true); // keep input track
87 }
88 // compute the number of shared hits from the number of max shared modules
89 // reset every track as could be changed for tracks within an ROI
90 // ROI matching is done within decideWhichHitsToKeep. Note mulitple ROI types
91 double trackEta = ptrTrack->trackParameters()->front()->eta();
92 int maxSharedModules = m_etaDependentCutsSvc.name().empty() ?
93 int(m_maxSharedModules) : m_etaDependentCutsSvc->getMaxSharedAtEta(trackEta);
94 cache.m_maxSharedModules = 2*maxSharedModules+1; // see header for meaning
95 cache.m_minNotShared = m_etaDependentCutsSvc.name().empty() ?
96 int(m_minNotSharedHits) : m_etaDependentCutsSvc->getMinSiNotSharedAtEta(trackEta);
97 cache.m_minSiHits = m_etaDependentCutsSvc.name().empty() ?
98 int(m_minSiHitsToAllowSplitting) : m_etaDependentCutsSvc->getMinSiHitsAtEta(trackEta);
99
100 // cut on TRT hits, might use eta dependent cuts here
101 int nCutTRT = m_minTRT_Hits;
102 if (m_parameterization) {
104 const Trk::TrackParameters* par = (*vpar)[0];
105 // ME bugfix TODO ... how old is this comment??
106 int expected = m_selectortool->minNumberDCs(par);
107 if (expected > nCutTRT) nCutTRT = expected;
108 }
109
110 // get all TSOS the track
111 const Trk::TrackStates* tsos = ptrTrack->trackStateOnSurfaces();
112 ATH_MSG_DEBUG ("Study new Track "<< ptrTrack<<"\t , it has "<<tsos->size()<<"\t track states");
113
114 //Create structs to hold track information
115 //Values in here are used to decide if a track is kept or not
116 TrackHitDetails trackHitDetails;
117
118 ATH_MSG_DEBUG ("Filling in TrackDetails");
119 TSoS_Details tsosDetails(tsos->size());
120
121 // Fill structs with information
122 fillTrackDetails( ptrTrack, splitProbContainer, prd_to_track_map, trackHitDetails, tsosDetails);
123
124 //Decide which hits to keep
125 //This is a major function which checks the usage of each hit on the candidate track
126 ATH_MSG_DEBUG ("decideWhichHitsToKeep");
127 decideWhichHitsToKeep( ptrTrack, score, splitProbContainer, prd_to_track_map, trackHitDetails, tsosDetails, &cache, trackId );
128
129 ATH_MSG_DEBUG ("decideWhichHitsToKeep " << trackHitDetails.m_trkCouldBeAccepted );
130
131 //
132 // now see what to do with the track
133 //
134
135 ATH_MSG_DEBUG ("totalSiHits " << trackHitDetails.totalSiHits());
136 ATH_MSG_DEBUG ("totalUniqueSiHits " << trackHitDetails.totalUniqueSiHits());
137 ATH_MSG_DEBUG ("score " << score );
138
139
140 //------------------------------------------------------------------------------------//
141 //
142 // All tracks must pass a minimum set of criteria
143 //
144 // 1. Needs a minimum number of hits on track
145 // This cut is also implmeneted in the scoring tool and usually the same values are set.
146 // A track which fails to have the minimum number of hits, gets a score of 0
147 // and will not make it this far. Might not be true for all versions of scoring tools.
148 // The cut here maintains an explicit threshold
149 //
150 // 2. Needs enough TRT hits. This is an important cut for back-tracking
151 //
152 // 3. Needs to have enough unique hits (not shared with an accepted track)
153 //
154 //------------------------------------------------------------------------------------//
155 bool passBasicCuts(true);
156 if( trackHitDetails.totalSiHits() < m_minHits ) {
157 passBasicCuts = false;
158 if (m_observerTool.isEnabled()) {
160 }
161 }
162 if( trackHitDetails.m_numTRT_Unused < nCutTRT ) {
163 passBasicCuts = false;
164 if (m_observerTool.isEnabled()) {
166 }
167 }
168 if( trackHitDetails.totalUniqueSiHits() < cache.m_minNotShared ) {
169 passBasicCuts = false;
170 if (m_observerTool.isEnabled()) {
172 }
173 }
174 if( !passBasicCuts ) {
175 ATH_MSG_DEBUG ("reject track; failed basic cuts");
176 return std::make_tuple(static_cast<Trk::Track *>(nullptr),false); // reject input track
177 }
178 //------------------------------------------------------------------------------------//
179
180
181 //------------------------------------------------------------------------------------//
182 //
183 // Decide to keep track or not based on more complex criteria
184 // 1. Check if track passes some criteria, including decision from decideWhichHitsToKeep
185 // If it passes, put the track into the output collection
186 // 2. Those which fail are tested on a second set of criteria
187 // If it passes, strip off "RejectedHits" (decided in decideWhichHitsToKeep)
188 // and build new subtrack from all non-shared hits and the
189 // set of shared hits which pass some cuts.
190 // If 1. new track would have same hit content, save the original track
191 // 2. if the new subtrack has less hits, and more than the min, created
192 // subtrack and reject the original
193 // 3. if the new subtrack is below min hit cuts, junk it
194 // 3. Those which fail are rejected with no chance for recovery
195 //
196 //------------------------------------------------------------------------------------//
197
198 //------------------------------------------------------------------------------------//
199 // Set some booleans for the up coming if/else statement
200
201 // no shared hit at all
202 // if shared hits, have additional requirements to check (3)
203 bool noSharedHits( trackHitDetails.m_numShared == 0 );
204
205 // set 2 bools for criteria placed on tracks with shared hits each criteria
206 // 1/2 - too many shared modules?
207 bool passSharedModulesCut( trackHitDetails.m_numWeightedShared < cache.m_maxSharedModules );
208
209 // 2/2 - good quality?
210 // Note, all tracks with a score of 0 are already removed
211 bool passScoreCut( score > m_minScoreShareTracks );
212 //------------------------------------------------------------------------------------//
213
214
215 //------------------------------------------------------------------------------------//
216 // Execute logic outlined above
217 //
218 // BEST CASE, we like this track and it passes this if statement
219 // if have shared hits, not too many shared, and score ("quality") (note unique hits checked above)
220 if( trackHitDetails.m_trkCouldBeAccepted &&
221 ( noSharedHits || (passSharedModulesCut && passScoreCut) ) ) {
222 ATH_MSG_DEBUG ("=> Suggest to keep track with "<<trackHitDetails.m_numShared<<" shared hits !");
223
224
225 // Change pixel hits property for shared hits as this track will be accepted into the final track colection
226 if (!trackHitDetails.m_isPatternTrack){
227 setPixelClusterSplitInformation( tsosDetails, splitProbContainer );
228 }
229
230 if (m_observerTool.isEnabled()){
232 }
233 return std::make_tuple(static_cast<Trk::Track *>(nullptr),true); // keep input track
234
235 }
236 // Track failed to be accepted as is.
237 // Can we recover the track?
238 else if ( passScoreCut ) {
239
240 // catch, if this is cosmics, accept the incoming track
241 if (m_cosmics) {
242 ATH_MSG_DEBUG ("=> Cosmics, accept input track even with shared hits");
243 if (m_observerTool.isEnabled()){
245 }
246 return std::make_tuple(static_cast<Trk::Track *>(nullptr),true); // keep input track
247 }
248
249 //
250 // Track is potentially ok, create a stripped down version
251 // from all hits not rejected
252 //
253
254 ATH_MSG_VERBOSE ("Trying to recover track...gathering hits.");
255
256 // decision on hits are already made
257 // check the cleaning cuts and see if any of the rejected hits can be added back in
258 // otherwise, go with what we have
259 //
260 // A candidate below the total hit cut will never make it this far.
261 // We are only extend tracks here if ever decide to override rejected hit decisions
262
263 // loop over all TSOS (and types) and copy the good
264 // ones over to new TSOS vector
265 std::vector<const Trk::TrackStateOnSurface*> newTSOS;
266
267 // iterators for looping
269 Trk::TrackStates::const_iterator iTsosEnd = tsos->end();
270
271 for (int index = 0 ; iTsos != iTsosEnd ; ++iTsos,++index ) {
272
273 // remove rejected hits
274 if( tsosDetails.m_type[index] == RejectedHitOverUse ||
275 tsosDetails.m_type[index] == RejectedHitInvalid ||
276 tsosDetails.m_type[index] == RejectedHit ) {
277 ATH_MSG_VERBOSE ("-> Dropping rejected hit");
278 continue;
279 }
280
281 ATH_MSG_VERBOSE ("-> Copy good TSOS");
282 newTSOS.push_back(*iTsos);
283
284 } // loop over TSOS
285
286
287 // newTSOS size would be hits on new track...how can the limit be 3? Is this backtracking?
288 // Missing something? What configuration is relying on this cut? TODO
289 if ( newTSOS.size() <= 3 ) {
290 ATH_MSG_VERBOSE ("newTSOS.size(): "<<newTSOS.size() );
291 ATH_MSG_DEBUG ("reject track; Too few hits, reject track with shared hits");
292 if (m_observerTool.isEnabled()){
294 }
295 return std::make_tuple(static_cast<Trk::Track *>(nullptr),false); // reject input track
296 }
297
298 // check that this is not the input track
299 if ( newTSOS.size() == tsos->size() ) {
300 ATH_MSG_DEBUG ("=> Recovered input track, accept it !");
301
302 // Change pixel hits property for shared hits as this is track will be accepeted into the final track colection
303 if (!trackHitDetails.m_isPatternTrack){
304 setPixelClusterSplitInformation( tsosDetails, splitProbContainer );
305 }
306 ATH_MSG_DEBUG ("reject track; maybe track was mark as rejected, but we recoverd it so no rejection");
307 if (m_observerTool.isEnabled()){
309 }
310 return std::make_tuple(static_cast<Trk::Track *>(nullptr),true); // keep input track
311 } else {
312 // ok, done, create subtrack
313 Trk::Track* newTrack = createSubTrack(newTSOS,ptrTrack);
314 if (!newTrack) {
315 ATH_MSG_DEBUG ("=> Failed to create subtrack");
316 ATH_MSG_DEBUG ("reject track; Failed to create subtrack");
317 if (m_observerTool.isEnabled()){
319 }
320 return std::make_tuple(static_cast<Trk::Track *>(nullptr),false); // reject input track
321 }
322
323 Trk::TrackInfo info;
324 info.addPatternRecoAndProperties(ptrTrack->info());
325 Trk::TrackInfo newInfo;
327 info.addPatternReco(newInfo);
328 newTrack->info().addPatternReco(ptrTrack->info());
329
330 ATH_MSG_DEBUG ("=> Successfully created subtrack with shared hits recovered !");
331 if (m_observerTool.isEnabled()) {
333 m_observerTool->addSubTrack(subtrackId, trackId, *newTrack);
334 }
335 return std::make_tuple(newTrack,false); // create new, cleaned track and reject input track
336 }
337 }
338
339 // if made it this far, junk the track
340 ATH_MSG_DEBUG ("=> Track is recommended to be dropped");
341 ATH_MSG_DEBUG ("reject track; other");
342 if (m_observerTool.isEnabled()){
344 }
345 return std::make_tuple(static_cast<Trk::Track *>(nullptr),false); // reject input track
346
347}
348
349
350//
351// Check if a shared hit invalidates any accepted track, if so, return false
352// otherwise return true
353// ONLY Shared hits are expected. We assume the decision to split has already been made
355 int index,
356 Trk::ClusterSplitProbabilityContainer &splitProbContainer,
357 Trk::PRDtoTrackMap &prd_to_track_map,
358 int& maxiShared,
359 int& maxOtherNPixel,
360 bool& maxOtherHasIBL,
361 CacheEntry* ent) const
362{
363
364 // Hits here are only shared hits.
365 // Assumption: the decision to split has been done outside this function
366 if( tsosDetails.m_type[index] != SharedHit ) {
367 ATH_MSG_WARNING("Calling checkOtherTracksValidity with a hit that is not shared!");
368 return true;
369 }
370
371 // needed?
372 const Trk::RIO_OnTrack* rot = tsosDetails.m_RIO[index];
373
374 // get list of tracks that use this hit already
375 int numberOfTracksWithThisPrd = tsosDetails.m_hitIsShared[index];
376 ATH_MSG_VERBOSE ("---> number of tracks with this shared Prd: " << numberOfTracksWithThisPrd << " maxtracks: " << m_maxTracksPerPRD);
377
378 // check if adding one more shared hit would push any accepted track
379 // -over the limit of shared hits
380 // -under the limit of unique hits
381 maxiShared = -1;
382 bool otherwillFailMinHits = false;
383 bool otherwillFailSCTuniqueHits = false;
384
385 //Setup counters
386 int iSharedMod = 0; //Number of Shared modules on the accepted track (will include this hit)
387 int iNotShared = 0; //Number of unshared hits on the accepted track
388 int iSctUnique = 0; //Number of unique SCT hits on the accepted track
389 int iPixel = 0; //Number of pixel hits on the accepted track
390 int iSCT = 0; //Number of SCT hits on the accepted track
391 bool iHasBlayer = false; // Does the accepted track have a b-layer hit
392
393 // loop over all tracks that have this hit and make sure none fail
394 // - requirement on unique hits
395 // - requirement on shared modules
396 // - requirement on unique sct hits
397 // send back some information about the most overlapping track
398 auto currentHitsSharedTracks = tsosDetails.m_tracksSharingHit.equal_range(index);
399 for ( auto track = currentHitsSharedTracks.first; track != currentHitsSharedTracks.second; ++track ){
400
401 //Count up the hit properties of the track you are inspecting
402 iSharedMod = 0;
403 iNotShared = 0;
404 iSctUnique = 0;
405 iPixel = 0;
406 iHasBlayer = false;
407 iSCT = 0;
408
409 std::vector< const Trk::PrepRawData* > prdsToCheck = m_assoTool->getPrdsOnTrack(prd_to_track_map, *(track->second));
410 for (const Trk::PrepRawData* prdToCheck : prdsToCheck) {
411 bool isPixel(false);
412 bool isSplitPixel(false);
413 if (m_detID->is_pixel(prdToCheck->identify())) {
414 isPixel = true;
415 if (prdToCheck->type(Trk::PrepRawDataType::PixelCluster)){
416 const InDet::PixelCluster* constPixelCluster = static_cast<const InDet::PixelCluster*> ( prdToCheck );
417 const Trk::ClusterSplitProbabilityContainer::ProbabilityInfo &splitProb = splitProbContainer.splitProbability(constPixelCluster);
418 if ( splitProb.isSplit() ) {
419 isSplitPixel = true;
420 }
421 }
422
423 ++iPixel;
424 if (m_detID->is_blayer(prdToCheck->identify()) ) iHasBlayer=true;
425 }
426
427 if ( m_detID->is_sct(prdToCheck->identify()) ) {
428 ++iSCT;
429 }
430
431 //
432 // count for general cases considering current flags (i.e. if split can be shared)
433 // hit which are overused, are rejected and should not be in this part of the code
434 // if hit is new one to be shared, count it as shared
435 // - the new cluster to be shared is not a split cluster (that is why we are here)
436 // - this will count correctly if a split hit can also be shared
437 if ( rot->prepRawData() == prdToCheck ) {
438 iSharedMod += isPixel ? 2 : 1;
439 // else if hit is not the new hit to be shared, then see if it is already shared
440 // - if so, count considering if it is split or not
441 } else if ( prd_to_track_map.isShared( *prdToCheck ) ) {
442 iSharedMod += isSplitPixel ? 0 : isPixel ? 2 : 1;
443 // else
444 // - not a shared cluster
445 } else {
446 ++iNotShared;
447 if (m_detID->is_sct(prdToCheck->identify())){
448 ++iSctUnique;
449 }
450 }
451 } // loop over PRDs
452
453 ATH_MSG_VERBOSE( "Track " << track->second << " will has " << iNotShared << " unique hits and " << iSctUnique << " unique SCT hits.");
454 // You are sharing too many hits reject the new track
455 // TODO does not include dead modules! Can we get that from the track summary?
456 if ( iNotShared < ent->m_minNotShared ) otherwillFailMinHits = true;
457 // You are sharing SCT hits and don't have enough to share -reject hit.
458 if ( iSCT > iSctUnique && iSctUnique < m_minUniqueSCTHits ) otherwillFailSCTuniqueHits = true;
459 } // loop over tracks
460
461 // Update details for the track with the most shared hits
462 if ( iSharedMod > maxiShared){
463 maxiShared = iSharedMod;
464 maxOtherNPixel = iPixel;
465 maxOtherHasIBL = iHasBlayer;
466 }
467
468 return !( otherwillFailMinHits || otherwillFailSCTuniqueHits );
469}
470
471
472
474 Trk::ClusterSplitProbabilityContainer &splitProbContainer,
475 const Trk::PRDtoTrackMap &prd_to_track_map,
476 TrackHitDetails& trackHitDetails,
477 TSoS_Details& tsosDetails) const
478{
479
480 // get all TSOS the track
481 const Trk::TrackStates* tsos = ptrTrack->trackStateOnSurfaces();
482 ATH_MSG_DEBUG ("Study new Track "<< ptrTrack<<"\t , it has "<<tsos->size()<<"\t track states");
483
484
485 // is this a track from the pattern or a fitted track ?
486 trackHitDetails.m_isPatternTrack = (ptrTrack->info().trackFitter()==Trk::TrackInfo::Unknown);
487 if (trackHitDetails.m_isPatternTrack) {
488 ATH_MSG_DEBUG ("-> this is a pattern track, outliers are good hits (reintegration) ! " << ptrTrack->perigeeParameters() );
489 } else {
490 ATH_MSG_DEBUG ("-> this is a refitted track, so we can use the chi2 ! " << ptrTrack->perigeeParameters());
491 }
492
493 // some pre-processing of the summary information, if available, needed for special cuts
494 const Trk::TrackSummary* trkSummary=ptrTrack->trackSummary();
495 if (trkSummary) {
496 ATH_MSG_VERBOSE ("--> Found summary information");
497 trackHitDetails.m_numPixelDeadSensor = trkSummary->get(Trk::numberOfPixelDeadSensors);
498 trackHitDetails.m_numSCTDeadSensor = trkSummary->get(Trk::numberOfSCTDeadSensors);
499 trackHitDetails.m_numPixelHits = trkSummary->get(Trk::numberOfPixelHits);
500 trackHitDetails.m_numPixelHoles = trkSummary->get(Trk::numberOfPixelHoles);
501 trackHitDetails.m_numSCTHoles = trkSummary->get(Trk::numberOfSCTHoles);
502 trackHitDetails.m_numSCTHits = trkSummary->get(Trk::numberOfSCTHits);
503 } else {
504 ATH_MSG_WARNING("Did not find track summary. Some cuts will be less efficienct!");
505 }
506
507
508 // set nDeadSensors to 0 in case trkSummary wasn't called with HoleSearch
509 // (i.e. number of deadSensors not available)
510 if (trackHitDetails.m_numPixelDeadSensor == -1) trackHitDetails.m_numPixelDeadSensor = 0;
511 if (trackHitDetails.m_numSCTDeadSensor == -1) trackHitDetails.m_numSCTDeadSensor = 0;
512 ATH_MSG_VERBOSE ("--- Number of dead si sensors: " << trackHitDetails.m_numPixelDeadSensor + trackHitDetails.m_numSCTDeadSensor);
513
514
515 //
516 // loop over TSOS and save information about each
517 // label each TSOS as Outlier, UnusedHit, SharedHit or RejectedHit (only for errors here)
518 // labels are used refined in decideWhichHitsToKeep
519 ATH_MSG_VERBOSE ("--> Looping over TSOS's");
521 Trk::TrackStates::const_iterator iTsosEnd = tsos->end();
522 for (int index = 0 ; iTsos != iTsosEnd ; ++iTsos, ++index) {
523
524 // get measurment from TSOS
525 const Trk::MeasurementBase* meas = (*iTsos)->measurementOnTrack();
526
527 // if we do not have a measurement, we should just mark it
528 if (!meas) {
529 ATH_MSG_VERBOSE ( Form("---> No measurement on TSOS, it is another type, %2d",index) );
530 tsosDetails.m_type[index] = OtherTsos;
531 continue;
532 }
533
534 // ok, let try to get the ROT then
535
537 // could be a Pseudo-Measurement ?
539 ATH_MSG_VERBOSE ( Form("---> Pseudo measurement, %2d",index) );
540 ++trackHitDetails.m_numPseudo; // increase counter
541 } else {
542 ATH_MSG_WARNING ( Form("---> Measurement is not a pseudo measurment, not yet supported! %2d",index));
543 }
544 tsosDetails.m_type[index] = OtherTsos;
545 continue;
546 }
547 const Trk::RIO_OnTrack* rot = static_cast <const Trk::RIO_OnTrack*> (meas);
548 //Store RIO into vector for later use
549 tsosDetails.m_RIO[index] = rot;
550
551 //
552 // we have a TSOS with a measurement, keep analysing it
553 //
554
555 // let's get some information about the measurement
556 const Identifier& id = rot->identify();
557 bool isTRT = m_detID->is_trt(id);
558 bool isPixel = m_detID->is_pixel(id);
559 bool isSCT = m_detID->is_sct(id);
560 bool isIBL = isPixel ? m_detID->is_blayer(id) : false; // checks layer 0
561 bool isoutlier = (*iTsos)->type(Trk::TrackStateOnSurface::Outlier);
562
563 tsosDetails.m_detType[index] = isTRT * 3 + isSCT * 2 + isPixel * 1 + isIBL * 10;
564
565 // Do we have a IBL hit on the track?
566 if ( isIBL && (!isoutlier || trackHitDetails.m_isPatternTrack ) ) {
567 trackHitDetails.m_thisHasIBLHit = true; // we may reintegrate outliers from pattern
568 }
569
570 // Add splitting information about the cluster
571 if (isPixel) {
573 ATH_MSG_WARNING ("---> Cluster is not from pixels; should not happen !");
574 tsosDetails.m_type[index] = RejectedHit;
575 continue;
576 } else {
577 // get pixel cluster
578 const InDet::PixelCluster* clus = static_cast <const InDet::PixelCluster*> (rot->prepRawData());
579 const Trk::ClusterSplitProbabilityContainer::ProbabilityInfo &splitProb = splitProbContainer.splitProbability(clus);
580 if ( !splitProb.isTooBigToBeSplit() ) {
581 tsosDetails.m_splitProb1[index] = splitProb.splitProbability1();
582 tsosDetails.m_splitProb2[index] = splitProb.splitProbability2();
583 } else {
584 // cluster too big to split are default to 3 particle cluster
585 // rigorously checked?
586 tsosDetails.m_splitProb1[index] = m_sharedProbCut - 0.01f;
587 tsosDetails.m_splitProb2[index] = m_sharedProbCut2 + 0.01f;
588 }
589 }
590 } // isPixel
591
592
593 //
594 // define each hit
595 // continue once definition set
596 //
597
598 // is this cluster used on an accepted track?
599 bool isUsed = prd_to_track_map.isUsed(*(rot->prepRawData()));
600
601 // assign outlier label using isoutlier bool above
602 // or if not inDet (does this even happen? Historical criteria)
603 // further criteria on keeping a hit or not is done in decideWhichHitsToKeep
604 // NOTE outliers can be shared but cannot save both in tsosDetails
605 if( isoutlier || !(m_detID->is_indet(id))) {
606 ATH_MSG_VERBOSE ( Form("---> Prd is outlier, %d", index) );
607 tsosDetails.m_type[index] = Outlier;
608 // if it is used, we need to send that information to the rest of the code
609 // in decideWhichHitsToKeep we reject any outlier used on another track
610 // if that logic was to change, and the number of tracks was needed, this would
611 // need to change
612 if(isUsed) { tsosDetails.m_hitIsShared[index] = 1; }
613 continue;
614 }
615
616
617 if (!isUsed) {
618 ATH_MSG_VERBOSE ( Form("---> Prd is unused, %d", index) );
619 tsosDetails.m_type[index] = UnusedHit;
620 continue;
621 }
622
623 //
624 // we have a shared hit
625 //
626
627
628 // check if it is a shared TRT hit, this is not allowed
629 if (isTRT) {
630 ATH_MSG_VERBOSE ( Form("---> Share TRT hit, drop it !, %d", index) );
631 tsosDetails.m_type[index] = RejectedHit;
632 continue;
633 }
634
635 /* Allow a hit to be a shared one, if
636 - not too many tracks share this hit already
637 - the score of the track is high enough to allow for shared hits
638 store information here but make decisions in decideWhichHitsToKeep
639 */
641 int numberOfTracksWithThisPrd = std::distance(range.first,range.second);
642 ATH_MSG_VERBOSE ( Form("---> Number of tracks with this share Prd %d: %2d maxtracks: %2d",index, numberOfTracksWithThisPrd, m_maxTracksPerPRD.value()) );
643 tsosDetails.m_hitIsShared[index] = numberOfTracksWithThisPrd;
644
645
646 // get iterators for range
647 Trk::PRDtoTrackMap::PrepRawDataTrackMap::const_iterator mapIt = range.first;
648 Trk::PRDtoTrackMap::PrepRawDataTrackMap::const_iterator mapItEnd = range.second;
649 // simple for loop instead of fancier remove_if above
650 for ( ;mapIt!=mapItEnd; ++mapIt) {
651 tsosDetails.m_overlappingTracks.insert( std::pair<const Trk::Track*, int >(mapIt->second, index) );
652 tsosDetails.m_tracksSharingHit.insert(std::pair< int, const Trk::Track* >(index, mapIt->second ) );
653 }
654
655 ATH_MSG_VERBOSE ("-----> Mark this hits as shared -- Try and recover later!");
656 ATH_MSG_VERBOSE ("------ Index: "<< index << " Type: " << tsosDetails.m_detType[index] << " splitprob1 " << tsosDetails.m_splitProb1[index]);
657 tsosDetails.m_type[index] = SharedHit;
658 } // End loop over TSOS's
659
660 }
661
662//==========================================================================================
663//
664// look at cluster properties and how often they are used to determine if can stay on track
665//
667 const Trk::TrackScore score,
668 Trk::ClusterSplitProbabilityContainer &splitProbContainer,
669 Trk::PRDtoTrackMap &prd_to_track_map,
670 TrackHitDetails& trackHitDetails,
671 TSoS_Details& tsosDetails,
672 CacheEntry* ent,
673 int trackId) const
674{
675
676 // Can the track automatically be accepted without further checks
677 trackHitDetails.m_trkCouldBeAccepted = true;
678
679 // Does this track fall into an hadronic ROI?
680 trackHitDetails.m_passHadronicROI = false;
681 if( m_useHClusSeed && inHadronicROI(ptrTrack) ) {
682 trackHitDetails.m_passHadronicROI = true;
683 }
684
685
686 //------------------------------------------------------------------//
687 // Should a shared hit be called shared or is it compatible with multiple clusters?
688 // this flag controls if the additional information is conisdered and shared hits on this track
689 // are "recovered" from the shared state to the split state
690 //
691 // First criteria are checked which would NOT allow recovery
692 // Then override criteria are checked
693 bool recoverSharedHits(true);
694 // reasons NOT to consider the information
695 // not above pT for splitting
696 if( ptrTrack->trackParameters()->front()->pT() < m_minPtSplit ) { recoverSharedHits = false; }
697 // score too low
698 if(score <= m_minScoreShareTracks) { recoverSharedHits = false; }
699 // the following 2 cuts use information from the track summary stored in the details struct
700 // not enough SiHits
701 if(trackHitDetails.m_numPixelHits+trackHitDetails.m_numSCTHits < m_minSiHitsToAllowSplitting) {
702 recoverSharedHits = false;
703 }
704 // too many holes
705 if(trackHitDetails.m_numPixelHoles>1) { recoverSharedHits = false; }
706
707
708
709 //------------------------------------------------------------------//
710 //
711 // loop over all measurements, make decisions, increment counters
712 //
713 for (unsigned int index(0); index < tsosDetails.m_nTSoS; ++index ){
714 //Skip all non-measurement TSOS's
715 if (tsosDetails.m_type[index] == OtherTsos) { continue; }
716
717 // in fillTrackDetails, if an error, cluster could be rejected
718 // also shared TRT hits are rejected there
719 if (tsosDetails.m_type[index] == RejectedHit) { // only generic rejects at that point
720 trackHitDetails.m_trkCouldBeAccepted = false; // we have to remove at least one PRD
721 if (m_observerTool.isEnabled()){
723 }
724 continue;
725 }
726
727 // Keep all unused hits
728 if (tsosDetails.m_type[index] == UnusedHit ){
729 if ( tsosDetails.m_detType[index] == 3 ) {
730 ++trackHitDetails.m_numTRT_Unused;
731 } else {
732 ++trackHitDetails.m_numUnused;
733 if ( tsosDetails.m_detType[index] == 2 ) { ++trackHitDetails.m_numSCT_Unused; }
734 }
735 continue;
736 }
737
738 //===================================================================//
739 //
740 // OUTLIERS - not type Outlier is given to both Shared and UnShared hits. Sort it out here
741 // Note in fillTrackDetails, for outliers we saved "1" in m_hitIsShared for any used hit,
742 // even if the true value is higher. As we will reject them here, it does not matter
743 // how many it is shared with
744 // if a pattern track
745 // - used : reject the hit
746 // - unused : call it unused and move on (reintegration of pattern outliers)
747 // if fitted track
748 // - used : reject the hit
749 // - unused : keep it but do not call it an unused hit (not counted towards total SiHit count)
750 //
751 if( tsosDetails.m_type[index] == Outlier ) {
752
753 // if on another track, get it off of this one
754 // for an outlier, we need to check m_hitIsShared to see if it used
755 if( tsosDetails.m_hitIsShared[index]>0 ) { // hit is used on another track
756 ATH_MSG_VERBOSE( Form("---> Prd is outlier and shared, reject it. %d", index) );
757 rejectHit(trackHitDetails, tsosDetails, index);
758 if (m_observerTool.isEnabled()){
760 }
761 continue;
762 }
763
764 if(trackHitDetails.m_isPatternTrack) {
765
766 // For pattern tracks:
767 // if used : reject it --> see above
768 // if unused : reintegrate it and send to track fit
769 ATH_MSG_VERBOSE ( Form("---> Prd is outlier on a pattern track and is unused, %d", index) );
770 // change to unused hit, increment counter
771 tsosDetails.m_type[index] = UnusedHit; // change name so m_numUnused matches types on track
772 ++trackHitDetails.m_numUnused;
773 if( tsosDetails.m_detType[index]%10 == 2 ) { ++trackHitDetails.m_numSCT_Unused; }
774 continue;
775 }
776 else { // is outlier on fitted track and ...
777 // used : reject the hit --> see above
778 // unused: send it through, but do not count it towards the hit content
779 ATH_MSG_DEBUG( Form("---> Prd is outlier on a fitted track and is unused, %d", index) );
780 continue;
781 } // m_isPatternTrack or not
782 } // isOutlier or not
783 //===================================================================//
784
785 // cleaning cut: fitted track with 1 pixel hit without an IBL hit
786 /* hurts conversion performance, slighly better perf in min-bias without it
787 * but high pT jets can use this in the core
788 if(!trackHitDetails.m_isPatternTrack && // fitted track
789 trackHitDetails.m_numPixelHits==1 && // 1 pixel hit
790 !trackHitDetails.m_thisHasIBLHit && // no IBL hits
791 tsosDetails.m_detType[index]%10 == 1 && // index is the pixel hit
792 !(tsosDetails.m_type[index]==Outlier)) { // and it is not an outlier)
793 ATH_MSG_VERBOSE ("-> Special case, problematic single pixel hit on fitted track, reject it !");
794 TrkCouldBeAccepted = false; // we have to remove at least one PRD
795 tsosDetails.m_type[index] = RejectedHit;
796 continue;
797 }
798 */
799
800 // At this point, only hits labeled shared from fillTrackDetails
801 if( tsosDetails.m_type[index] != SharedHit ) {
802 ATH_MSG_ERROR("A NON-Shared hit is being treated as one!");
803 }
804
805 //===================================================================//
806 // Try and recover shared hits if
807 // - pixel cluster splitting flag is turned on
808 // - track passes criteria for cluster splitting
809 // - is a pixel hit
810 if ( m_doPixelClusterSplitting && recoverSharedHits && tsosDetails.m_detType[index]%10 == 1 ) {
811
812 //Find the index of the previous measurement on track
813 int indexPreviousMeasurement = tsosDetails.findIndexOfPreviousMeasurement(index);
814 if (indexPreviousMeasurement > 0 ) {
815 ATH_MSG_VERBOSE ("--> Previous Measurement was at : " << indexPreviousMeasurement
816 << " and was a: " << tsosDetails.m_type[indexPreviousMeasurement]
817 << " with splitprob1 " << tsosDetails.m_splitProb1[indexPreviousMeasurement]
818 << " and splitprob2 " << tsosDetails.m_splitProb2[indexPreviousMeasurement]);
819 }
820
821 // If the previous measurement is a shared pixel and the current pixel
822 // - wants to be shared
823 // - and is compatible with being from multiple clusters
824 // allow the previous measurement to be shared with up to m_maxTracksPerPRD tracks without penalty
825 if ( indexPreviousMeasurement >= 0 &&
826 tsosDetails.m_type[indexPreviousMeasurement] == SharedHit &&
827 tsosDetails.m_hitIsShared[indexPreviousMeasurement] < m_maxTracksPerPRD &&
828 clusCanBeSplit(tsosDetails.m_splitProb1[index],tsosDetails.m_splitProb2[index]) ) {
829
830 // Check if the previous shared hit shared on the same track as this one
831 bool sharedbetweenthesametracks = false;
832 auto previousHitsSharedTracks = tsosDetails.m_tracksSharingHit.equal_range(indexPreviousMeasurement);
833 auto currentHitsSharedTracks = tsosDetails.m_tracksSharingHit.equal_range(index);
834 for (auto iteratorP = previousHitsSharedTracks.first;
835 iteratorP != previousHitsSharedTracks.second; ++iteratorP) {
836 for (auto iteratorC = currentHitsSharedTracks.first;
837 iteratorC != currentHitsSharedTracks.second; ++iteratorC) {
838 if ( iteratorC->second == iteratorP->second){
839 sharedbetweenthesametracks = true;
840 break;
841 }
842 }
843 if (sharedbetweenthesametracks) break;
844 }
845 if (sharedbetweenthesametracks){
846 sharedToSplitPix(trackHitDetails, tsosDetails, indexPreviousMeasurement);
847 }
848 }
849
850 //
851 // Check the number network.
852 // - check if the particle is compatible with 2 particles
853 // - else check if particle is compatible with >= 3 particles
854 // - else it is a 1 particle cluster
855 // Is a 2 particle cluster?
856 if ( isTwoPartClus(tsosDetails.m_splitProb1[index],tsosDetails.m_splitProb2[index]) ) {
857
858 // can be split, but how many accepted tracks use the hit?
859 // okay to share
860 if (tsosDetails.m_hitIsShared[index] < m_maxPixTwoPartCluster) {
861 ATH_MSG_VERBOSE ("---> Pixel cluster is to be split shared with another track: Split Prob1 " << tsosDetails.m_splitProb1[index] );
862 tsosDetails.m_type[index] = SplitSharedHit;
863 ++trackHitDetails.m_numSplitSharedPix;
864 continue;
865 } else if(m_shareSplitHits && tsosDetails.m_hitIsShared[index] == m_maxPixTwoPartCluster) {
866 // if we allow split hits to also be shared
867 // - the first m_maxPixTwoPartCluster cluster get to use it without penalty
868 // - the m_maxPixTwoPartCluster+1 cluster gets called shared
869 ATH_MSG_VERBOSE ("---> Pixel cluster is split, but must be called shared to stay on this track!");
870 addSharedHit(trackHitDetails, tsosDetails, index);
871 continue;
872 } else {
873 ATH_MSG_VERBOSE ("---> Pixel split but shared between too many tracks -- will be removed from the track!!!");
874 rejectHitOverUse(trackHitDetails, tsosDetails, index);
875 if (m_observerTool.isEnabled()){
877 }
878 continue;
879 }
880
881 // Is a 3+ particle cluster?
882 } else if ( isMultiPartClus(tsosDetails.m_splitProb2[index]) ) {
883
884 // can be split, but how many accepted tracks use the hit?
885 // okay to share
886 if (tsosDetails.m_hitIsShared[index] < m_maxPixMultiCluster ){
887 ATH_MSG_VERBOSE ("---> Pixel cluster is to be split shared with another track: Split Prob2 " << tsosDetails.m_splitProb2[index] );
888 tsosDetails.m_type[index] = SplitSharedHit;
889 ++trackHitDetails.m_numSplitSharedPix;
890 continue;
891 } else if(m_shareSplitHits && tsosDetails.m_hitIsShared[index] == m_maxPixMultiCluster) {
892 // if we allow split hits to also be shared
893 // - the first m_maxPixMultiCluster cluster get to use it without penalty
894 // - the m_maxPixMultiCluster+1 cluster gets called shared
895 ATH_MSG_VERBOSE ("---> Pixel cluster is split, but must be called shared to stay on this track!");
896 addSharedHit(trackHitDetails, tsosDetails, index);
897 continue;
898 } else {
899 ATH_MSG_VERBOSE ("---> Pixel split but shared between too many tracks -- will be removed from the track!!!");
900 rejectHitOverUse(trackHitDetails, tsosDetails, index);
901 if (m_observerTool.isEnabled()){
903 }
904 continue;
905 }
906
907 } // end of checking number network output
908
909 ATH_MSG_VERBOSE("---> Pixel cluster is not compatible with being shared (splitProb1 = "
910 << tsosDetails.m_splitProb1[index] << "), (splitProb2 = "
911 << tsosDetails.m_splitProb2[index] << ") , reject shared hit !!!");
912 if ( tsosDetails.m_hitIsShared[index] < m_maxPixOnePartCluster ) {
913 // this is a shared cluster
914 addSharedHit(trackHitDetails, tsosDetails, index);
915 continue;
916 } else {
917 ATH_MSG_DEBUG ("reject track; Too many hits shared - we have to remove at least one PRD");
918 rejectHitOverUse(trackHitDetails, tsosDetails, index);
919 if (m_observerTool.isEnabled()){
921 }
922 continue;
923 }
924 }// End Attempt to recover shared hits
925 //===================================================================//
926
927 if( tsosDetails.m_hitIsShared[index] == 0 ) {
928 ATH_MSG_ERROR("A hit is not shared but is where only shared hits should be");
929 }
930
931 //For all other shared hits
932 if ( tsosDetails.m_hitIsShared[index] < m_maxTracksPerPRD ){ // we do not allow to share with too many tracks
933 ATH_MSG_VERBOSE ("---> Shared hit, but good track, let's enter hit in the list and try to keep it !");
934 ATH_MSG_VERBOSE ("----- Index: "<< index << " Type: " << tsosDetails.m_detType[index] << " splitprob1 " << tsosDetails.m_splitProb1[index]);
935 addSharedHit(trackHitDetails, tsosDetails, index);
936 continue;
937 } else {
938 ATH_MSG_DEBUG ("reject track; Too many hits shared - we have to remove at least one PRD");
939 rejectHitOverUse(trackHitDetails, tsosDetails, index);
940 if (m_observerTool.isEnabled()){
942 }
943 continue;
944 }
945 ATH_MSG_ERROR("Reached end of TSOS loop without a decision." );
946 } // loop over TSOS
947 //------------------------------------------------------------------//
948
949 //------------------------------------------------------------------//
950 //
951 // COUNTERS have been set above. From here on, if change the state
952 // of any hit, must also adjust counters
953 //
954 //------------------------------------------------------------------//
955
956 //------------------------------------------------------------------//
957 // Check if the pair is compatible with being a light particle decay
958 // This focuses on conversions
959 // The track in question must
960 // - have an overlapping hit with an accepted track
961 // - those two track have a small separation
962 //
963 trackHitDetails.m_passConversionSel = false; // make sure off to start
964 if (m_doPairSelection && !tsosDetails.m_overlappingTracks.empty()) {
965 trackHitDetails.m_passConversionSel = performConversionCheck(ptrTrack,
966 prd_to_track_map, trackHitDetails, tsosDetails);
967 }
968 //------------------------------------------------------------------//
969
970 //------------------------------------------------------------------//
971 // Also check if the pair is compatible with being a boosted hadronic topology.
972 // This branch focuses on high-pt taus and b-jets in particular
973 // Same conditions as above.
974 // Do not process any track already modified by the conversion check
975 //
976 if (m_useHClusSeed && !trackHitDetails.m_passConversionSel && trackHitDetails.m_passHadronicROI &&
977 m_doPairSelection && !tsosDetails.m_overlappingTracks.empty()) {
978 trackHitDetails.m_passConversionSel = performHadDecayCheck(ptrTrack,
979 prd_to_track_map, trackHitDetails, tsosDetails);
980 }
981
982 //------------------------------------------------------------------//
983 //
984 // Three cuts which can pull shared hits off of the track (no order)
985 // 1. min unique SCT hits to share hits
986 // 2. min chi2/ndf to share hits
987 //
988 // We shared SCT hits when we don't really have enough to share
989 // Reject SCT shared hits on the track
991 if ( trackHitDetails.m_numSCT_Unused != trackHitDetails.m_numSCTHits && // have shared SCT
992 trackHitDetails.m_numSCT_Unused < m_minUniqueSCTHits ){
993 for (unsigned int index( 0 ); index != tsosDetails.m_nTSoS; ++index ){
994 if ( tsosDetails.m_detType[index]==2 && tsosDetails.m_type[index] == SharedHit){
995 rejectSharedHit(trackHitDetails, tsosDetails, index);
996 if (m_observerTool.isEnabled()){
998 }
999 }
1000 }
1001 }
1002 }
1003
1004 // Cut on chi2/NDF if shared hits on track
1005 // if fail cuts, remove all shared hits and reject track
1006 if ( !trackHitDetails.m_isPatternTrack && trackHitDetails.m_numShared > 0) {
1007 double trackchi2 = 0;
1008 if (ptrTrack->fitQuality() && ptrTrack->fitQuality()->numberDoF()>0 ) {
1009 trackchi2 = ptrTrack->fitQuality()->chiSquared()/ptrTrack->fitQuality()->numberDoF();
1010 }
1011
1012 // if track fails cut for shared hits, remove the shared hits
1014 if ( trackchi2 > m_minTrackChi2ForSharedHits ) {
1015 ATH_MSG_DEBUG ("Shared hits, we have a bad chi2 track, mark it as bad !");
1016 // remove shared hits and see if track survives
1017 for (unsigned int index( 0 ); index != tsosDetails.m_nTSoS; ++index ){
1018 if ( tsosDetails.m_type[index] != SharedHit ) { continue; }
1019 rejectSharedHit(trackHitDetails, tsosDetails, index);
1020 if (m_observerTool.isEnabled()){
1022 }
1023 }
1024 } // fails cut
1025 }
1026 } // is not a pattern track and has shared hits
1027
1028 //------------------------------------------------------------------//
1029
1030
1031 //------------------------------------------------------------------//
1032 // Check accepted tracks with the surviving list of shared hits
1033 // Remove shared hits which push track over shared module cut
1034 // Set flags
1035 //
1036 // add up weighted count of shared hits on track, start removing
1037 // hits after counter is above cut. This preferences inner hits
1038 int newNumWeightedShared = 0; // tmp counter
1039 bool firstMeasurement(true);
1040 trackHitDetails.m_firstPixIsShared = false;
1041 // was already set in fillTrackDetails, but set again depending if blayer was rejected or not
1042 trackHitDetails.m_thisHasIBLHit = false;
1043 for (unsigned int index(0); index <tsosDetails.m_nTSoS; ++index ){
1044
1045 // don't count rejected hits when setting flags
1046 if (tsosDetails.m_type[index] == RejectedHitOverUse ||
1047 tsosDetails.m_type[index] == RejectedHitInvalid ||
1048 tsosDetails.m_type[index] == RejectedHit ){ continue; }
1049
1050 // Any track which is still labeled as SharedHit has to be checked
1051 // against the accepted tracks. Accepted track should not be pushed
1052 // above cuts imposed here, some historic cuts remain
1053 if (tsosDetails.m_type[index] == SharedHit) {
1054
1055 int maxiShared = -1;
1056 int maxOtherNPixel = 0;
1057 bool maxOtherHasIBL = false;
1058 bool otherPassMinUniqueHits = checkOtherTracksValidity( tsosDetails, index,
1059 splitProbContainer, prd_to_track_map, maxiShared, maxOtherNPixel,
1060 maxOtherHasIBL, ent);
1061
1062 if (!otherPassMinUniqueHits) {
1063 ATH_MSG_DEBUG ("reject track; Tracks shared hits does not leave enough unique hits on accepted track");
1064 rejectSharedHitInvalid(trackHitDetails, tsosDetails, index);
1065 if (m_observerTool.isEnabled()){
1067 }
1068 continue;
1069 }
1070
1071 //
1072 // do not allow other accepted track to exceed the shared limit...
1073 // ...IF first pixel hit is shared (historic cut)
1074 // NOTE: here "pixel" includes IBL
1075 // tightening cut by dropping shared hit clause impacts performance in high pT jet cores
1076 if( maxiShared >= ent->m_maxSharedModules ){
1077
1078 // if this is the first hit (it is shared), and a pixel, reject
1079 if( (tsosDetails.m_detType[index] % 10 == 1) && firstMeasurement ) {
1080 ATH_MSG_DEBUG ("reject track; Tracks shared hits pushes accepted track above shared module limit");
1081 rejectSharedHitInvalid(trackHitDetails, tsosDetails, index);
1082 if (m_observerTool.isEnabled()){
1084 }
1085 continue;
1086 }
1087 // if first pixel was shared (and this is not that hit)
1088 if( trackHitDetails.m_firstPixIsShared ) {
1089 ATH_MSG_DEBUG ("reject track; Tracks shared hits pushes accepted track above shared module limit");
1090 rejectSharedHitInvalid(trackHitDetails, tsosDetails, index);
1091 if (m_observerTool.isEnabled()){
1093 }
1094 continue;
1095 }
1096
1097 // unlinked (no truth particle) tracks tend to have low hit counts
1098 // don't let track that look like this touch accepted tracks (new)
1099 if( trackHitDetails.totalPixelHits() < m_minPixHitAccepted ) {
1100 rejectSharedHitInvalid(trackHitDetails, tsosDetails, index);
1101 if (m_observerTool.isEnabled()){
1103 }
1104 continue;
1105 }
1106
1107 } // accepted track exceeds shared module cuts
1108
1109
1110 //
1111 // only allow shared pixel if both have IBL or both not (historic cut)
1112 // if this is IBL hit, and other does not have IBL hit, remove shared IBL hit
1113 if( tsosDetails.m_detType[index] == 11 && !maxOtherHasIBL ) {
1114 ATH_MSG_VERBOSE ("---> Remove shared IBL as MaxShared accepted does not have an IBL hit");
1115 rejectSharedHit(trackHitDetails, tsosDetails, index);
1116 if (m_observerTool.isEnabled()){
1118 }
1119 continue;
1120 }
1121 // if this is pixel hit, and candidate does not match IBL content of MaxShared accepted, remove shared hit
1122 if(tsosDetails.m_detType[index] == 1 && (trackHitDetails.m_thisHasIBLHit != maxOtherHasIBL) ) {
1123 ATH_MSG_VERBOSE ("---> Only allow shared pixel if candidate and accepted have same IBL hit content");
1124 rejectSharedHit(trackHitDetails, tsosDetails, index);
1125 if (m_observerTool.isEnabled()){
1127 }
1128 continue;
1129 }
1130
1131 // number of shared modules to be added to new sub-track
1132 // add shared hit to temporary counter
1133 newNumWeightedShared += (tsosDetails.m_detType[index]%10== 1 ? 2 : 1); // increase counter
1134 // should remain below the threshold
1135 if (newNumWeightedShared >= ent->m_maxSharedModules) {
1136 ATH_MSG_VERBOSE ("-> Too many share hits, dropping outer hit(s) "
1137 << newNumWeightedShared << "\t" << ent->m_maxSharedModules);
1138 newNumWeightedShared -= (tsosDetails.m_detType[index]%10== 1 ? 2 : 1); // decrease counter
1139 rejectSharedHit(trackHitDetails, tsosDetails, index);
1140 if (m_observerTool.isEnabled()){
1142 }
1143 continue;
1144 }
1145
1146 //------------------------------------------//
1147 // if still shared and not rejected by above, set flags
1148 if( tsosDetails.m_detType[index] % 10 == 1 ) {
1149 if (firstMeasurement) {
1150 trackHitDetails.m_firstPixIsShared = true;
1151 }
1152 if (tsosDetails.m_detType[index] == 11 ){ // Blayer
1153 trackHitDetails.m_hasSharedIBLHit = true;
1154 } else if ( tsosDetails.m_detType[index] == 1 ){
1155 trackHitDetails.m_hasSharedPixel = true; // historic definition
1156 }
1157 } // pixel hit
1158
1159 } // if shared
1160
1161 if (tsosDetails.m_detType[index] == 11 ){ // Blayer
1162 trackHitDetails.m_thisHasIBLHit = true;
1163 }
1164 if (firstMeasurement && tsosDetails.m_type[index] != OtherTsos){ firstMeasurement = false; }
1165
1166 } // loop over TSOS
1167 //------------------------------------------------------------------//
1168
1169 if (msgLvl(MSG::VERBOSE)){
1170 trackHitDetails.dumpInfo();
1171 }
1172
1173 if (m_observerTool.isEnabled()){
1174 // calculate average split probabilities
1175 float splitProbAvg1 = -2;
1176 if (!tsosDetails.m_splitProb1.empty()){
1177 splitProbAvg1 = std::accumulate(tsosDetails.m_splitProb1.begin(), tsosDetails.m_splitProb1.end(), 0.0) / tsosDetails.m_splitProb1.size();
1178 }
1179 float splitProbAvg2 = -2;
1180 if (!tsosDetails.m_splitProb2.empty()){
1181 splitProbAvg2 = std::accumulate(tsosDetails.m_splitProb2.begin(), tsosDetails.m_splitProb2.end(), 0.0) / tsosDetails.m_splitProb2.size();
1182 }
1183 m_observerTool->updateHolesSharedHits(trackId,
1184 trackHitDetails.m_numPixelHoles,
1185 trackHitDetails.m_numSCTHoles,
1186 trackHitDetails.m_numSplitSharedPix,
1187 trackHitDetails.m_numSplitSharedSCT,
1188 -2,
1189 -2,
1190 trackHitDetails.m_numShared,
1191 trackHitDetails.m_isPatternTrack,
1192 trackHitDetails.totalSiHits(),
1193 trackHitDetails.m_passHadronicROI,
1194 trackHitDetails.m_thisHasIBLHit,
1195 trackHitDetails.m_hasSharedIBLHit,
1196 trackHitDetails.m_hasSharedPixel,
1197 trackHitDetails.m_firstPixIsShared,
1198 trackHitDetails.m_numPixelDeadSensor,
1199 trackHitDetails.m_numSCTDeadSensor,
1200 trackHitDetails.m_numPixelHits,
1201 trackHitDetails.m_numSCTHits,
1202 trackHitDetails.m_numUnused,
1203 trackHitDetails.m_numTRT_Unused,
1204 trackHitDetails.m_numSCT_Unused,
1205 trackHitDetails.m_numPseudo,
1206 splitProbAvg1,
1207 splitProbAvg2,
1208 trackHitDetails.m_numWeightedShared);
1209 }
1210
1211 } // decideWhichHitsToKeep
1212
1213//==========================================================================================
1214
1215// GOAL: Do not kill conversions in the ambi
1217 Trk::PRDtoTrackMap &prd_to_track_map,
1218 TrackHitDetails& trackHitDetails,
1219 TSoS_Details& tsosDetails) const
1220{
1221 ATH_MSG_DEBUG(" Conversion Check ");
1222
1223 // We need to have a good number of unshared SCT hits
1224 if ( trackHitDetails.m_numSCT_Unused < m_minUniqueSCTHits ) { return false; }
1225 if ( trackHitDetails.m_numPixelHoles + trackHitDetails.m_numSCTHoles >= 2) { return false; }
1226
1227 //Find the accepted track that shares the most hits our proposed track
1228 const Trk::Track* mostOverlappingTrack(nullptr);
1229 int mostOverlappingNumberOfHits(0);
1230 int indexOfFirstOverlappingHit(0);
1231 for ( std::multimap<const Trk::Track*,int>::iterator it = tsosDetails.m_overlappingTracks.begin(),
1232 end = tsosDetails.m_overlappingTracks.end(); it != end;
1233 it = tsosDetails.m_overlappingTracks.upper_bound(it->first) ) {
1234 int numberOfHitsSharedWithThisTrack = std::distance( it, tsosDetails.m_overlappingTracks.upper_bound(it->first));
1235 ATH_MSG_DEBUG(it->first <<" shares " << numberOfHitsSharedWithThisTrack << " hits with this track " );
1236 if (mostOverlappingNumberOfHits < numberOfHitsSharedWithThisTrack){
1237 mostOverlappingNumberOfHits = numberOfHitsSharedWithThisTrack;
1238 mostOverlappingTrack = it->first;
1239 indexOfFirstOverlappingHit = it->second;
1240 }
1241 } // loop over overlapping tracks
1242
1243 if(!mostOverlappingTrack) { return false; }
1244
1245 // criteria applied for fitted and pattern tracks
1246 if(mostOverlappingNumberOfHits < 2) { return false; }
1247 if(mostOverlappingNumberOfHits < trackHitDetails.m_numShared) { return false; }
1248
1249
1250 //If an overlapping track if found get the track parameters on the first shared surface
1251 auto tpPair = getOverlapTrackParameters(indexOfFirstOverlappingHit, ptrTrack, mostOverlappingTrack, prd_to_track_map, trackHitDetails.m_numSplitSharedPix );
1252
1253 // If found track parameters at first overlapping track, check separation
1254 if (tpPair.first && tpPair.second) {
1255 // Check a series of criteria to see if track is a compatible with a photon conversion
1256 // Check if both tracks are above threshold
1257 if(tpPair.first->pT() <= m_minPairTrackPt || tpPair.second->pT() <= m_minPairTrackPt) {
1258 return false;
1259 }
1260 //Check if it is in a ROI, if requested
1261 if(m_useEmClusSeed) {
1262 if(!isEmCaloCompatible( *tpPair.first )) { return false; }
1263 }
1264 ATH_MSG_DEBUG ("Possible photon conversion");
1265 }
1266 // for pattern tracks, cannot get the track parameters at a hit position
1267 // Need an alternate way to find conversion, try to use the accepted track
1268 // Main point is to not kill the pattern track
1269 else if ( trackHitDetails.m_isPatternTrack ) {
1270 if(m_useEmClusSeed && tpPair.second ) {
1271 if(!isEmCaloCompatible( *tpPair.second )) { return false; }
1272 }
1273 ATH_MSG_DEBUG ("Possible photon conversion - for pattern track");
1274 }
1275 // if cannot find track parameters, and not a pattern track, then failed
1276 else {
1277 return false;
1278 }
1279
1280 ATH_MSG_DEBUG ("Number of unused SCT hits: " << trackHitDetails.m_numSCT_Unused);
1281 if (msgLvl(MSG::DEBUG)){
1282 trackHitDetails.dumpInfo();
1283 }
1284 ATH_MSG_DEBUG ("Track "<< mostOverlappingTrack << " shares " << mostOverlappingNumberOfHits );
1285
1286 updateSharedForCollimated(trackHitDetails, tsosDetails);
1287
1288 return true;
1289} // performConversionCheck
1290
1291
1292// GOAL: Do not kill light particle decays in dense jets in the ambi.
1293// Based on conversion logic, but tuned towards later decays
1294// Heavily borrows from performConversionCheck, but
1295// separate implementation to for allow future fine-tuning
1296// distinct from the conversion version.
1298 Trk::PRDtoTrackMap &prd_to_track_map,
1299 TrackHitDetails& trackHitDetails,
1300 TSoS_Details& tsosDetails) const
1301{
1302 ATH_MSG_DEBUG(" Hadron decay Check ");
1303
1304 // We need to have a good number of unshared SCT hits
1305 if ( trackHitDetails.m_numSCT_Unused < m_minUniqueSCTHits ) { return false; }
1306 if ( trackHitDetails.m_numPixelHoles + trackHitDetails.m_numSCTHoles >= 2) { return false; }
1307
1308 //Find the accepted track that shares the most hits our proposed track
1309 const Trk::Track* mostOverlappingTrack(nullptr);
1310 int mostOverlappingNumberOfHits(0);
1311 int indexOfFirstOverlappingHit(0);
1312 for ( std::multimap<const Trk::Track*,int>::iterator it = tsosDetails.m_overlappingTracks.begin(),
1313 end = tsosDetails.m_overlappingTracks.end(); it != end;
1314 it = tsosDetails.m_overlappingTracks.upper_bound(it->first) ) {
1315 int numberOfHitsSharedWithThisTrack = std::distance( it, tsosDetails.m_overlappingTracks.upper_bound(it->first));
1316 ATH_MSG_DEBUG(it->first <<" shares " << numberOfHitsSharedWithThisTrack << " hits with this track " );
1317 if (mostOverlappingNumberOfHits < numberOfHitsSharedWithThisTrack){
1318 mostOverlappingNumberOfHits = numberOfHitsSharedWithThisTrack;
1319 mostOverlappingTrack = it->first;
1320 indexOfFirstOverlappingHit = it->second;
1321 }
1322 } // loop over overlapping tracks
1323
1324 if(!mostOverlappingTrack) { return false; }
1325
1326 // criteria applied for fitted and pattern tracks
1327 if(mostOverlappingNumberOfHits < 2) { return false; }
1328 if(mostOverlappingNumberOfHits < trackHitDetails.m_numShared) { return false; }
1329
1330
1331 //If an overlapping track if found get the track parameters on the first shared surface
1332 auto tpPair = getOverlapTrackParameters(indexOfFirstOverlappingHit, ptrTrack, mostOverlappingTrack, prd_to_track_map, trackHitDetails.m_numSplitSharedPix );
1333
1334 // If found track parameters at first overlapping track, check separation
1335 if (tpPair.first && tpPair.second) {
1336 // Check a series of criteria to see if track is a compatible with a boosted decay
1337 // Check if both tracks are above threshold
1338 if(tpPair.first->pT() <= m_minPairTrackPt || tpPair.second->pT() <= m_minPairTrackPt) {
1339 return false;
1340 }
1341 //Check if it is in a ROI, if requested
1342 if(m_useHClusSeed) {
1343 if(!isHadCaloCompatible( *tpPair.first )) { return false; }
1344 }
1345 ATH_MSG_DEBUG ("Possible boosted decay");
1346 }
1347 // for pattern tracks, cannot get the track parameters at a hit position
1348 else if ( trackHitDetails.m_isPatternTrack ) {
1349 if(m_useHClusSeed && tpPair.second ) {
1350 if(!isHadCaloCompatible( *tpPair.second )) { return false; }
1351 }
1352 ATH_MSG_DEBUG ("Possible boosted decay - for pattern track");
1353 }
1354 // if cannot find track parameters, and not a pattern track, then failed
1355 else {
1356 return false;
1357 }
1358
1359 ATH_MSG_DEBUG ("Number of unused SCT hits: " << trackHitDetails.m_numSCT_Unused);
1360 if (msgLvl(MSG::DEBUG)){
1361 trackHitDetails.dumpInfo();
1362 }
1363 ATH_MSG_DEBUG ("Track "<< mostOverlappingTrack << " shares " << mostOverlappingNumberOfHits );
1364
1365 updateSharedForCollimated(trackHitDetails, tsosDetails);
1366
1367 return true;
1368}
1369
1371 TSoS_Details& tsosDetails) const{
1372 //Change all shared SCT to SplitSharedHit
1373 ATH_MSG_VERBOSE ("Updating SCT hit information");
1374
1375 trackHitDetails.m_numSplitSharedPix = 0; // reset counter
1376 trackHitDetails.m_numSplitSharedSCT = 0; // reset counter
1377 trackHitDetails.m_numShared = 0; // reset counter
1378 trackHitDetails.m_numSCT_Shared = 0; // reset counter
1379 trackHitDetails.m_numWeightedShared = 0; // reset counter
1380
1381 trackHitDetails.m_hasSharedIBLHit = false; // reset flag
1382 trackHitDetails.m_hasSharedPixel = false; // reset flag
1383
1384 //Update counts but only allow 1 pixel hit to be updated free of charge
1385 int noUpdatedPixels = 0;
1386
1387 for (unsigned int index(0); index < tsosDetails.m_nTSoS; ++index ){
1388 // Dont change blayer only pixel hits -- all other shared hits become splitshared
1389 if ( noUpdatedPixels < 1 && tsosDetails.m_detType[index]==1 && tsosDetails.m_type[index] == SharedHit ){
1390 ++noUpdatedPixels;
1391 tsosDetails.m_type[index] = SplitSharedHit;
1392 }
1393
1394 if ( tsosDetails.m_detType[index]==1 && tsosDetails.m_type[index] == SplitSharedHit ){
1395 ++trackHitDetails.m_numSplitSharedPix;
1396 }
1397
1398 if ( tsosDetails.m_detType[index]==2 && tsosDetails.m_type[index] == SharedHit ){
1399 tsosDetails.m_type[index] = SplitSharedHit;
1400 }
1401
1402 if ( tsosDetails.m_detType[index]==2 && tsosDetails.m_type[index] == SplitSharedHit ){
1403 ++trackHitDetails.m_numSplitSharedSCT;
1404 }
1405
1406 // only change shared hits
1407 // m_numUnused and m_numSCT_Unused are not changed from this
1408 if (tsosDetails.m_type[index] != SharedHit){ continue; }
1409
1410 increaseSharedHitCounters( trackHitDetails,
1411 (tsosDetails.m_detType[index]%10 == 1),
1412 (tsosDetails.m_detType[index]%10 == 2) );
1413
1414 // set flags
1415 if (tsosDetails.m_detType[index] == 11){
1416 trackHitDetails.m_hasSharedIBLHit = true;
1417 } else if ( tsosDetails.m_detType[index] == 1 ){
1418 trackHitDetails.m_hasSharedPixel = true;
1419 }
1420
1421 } // loop over TSOS
1422}
1423
1424//==========================================================================================
1425Trk::Track* InDet::InDetDenseEnvAmbiTrackSelectionTool::createSubTrack( const std::vector<const Trk::TrackStateOnSurface*>& tsos, const Trk::Track* track ) const
1426{
1427 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tsosit=tsos.begin();
1428 int nmeas=0;
1429 for (;tsosit!=tsos.end();++tsosit){
1430 if ((**tsosit).type(Trk::TrackStateOnSurface::Measurement)) ++nmeas;
1431 }
1432 if (nmeas<3) {
1433 ATH_MSG_DEBUG ("Less than 3 measurements, reject track !");
1434 return nullptr;
1435 }
1436
1437 auto vecTsos = std::make_unique<Trk::TrackStates>();
1438
1439 // loop over TSOS, copy TSOS and push into vector
1440 for (const Trk::TrackStateOnSurface* iTsos : tsos) {
1441 const Trk::TrackStateOnSurface* newTsos = new Trk::TrackStateOnSurface(*iTsos);
1442 vecTsos->push_back(newTsos);
1443 }
1444
1445 Trk::TrackInfo info;
1446 info.addPatternRecoAndProperties(track->info());
1447 Trk::TrackInfo newInfo;
1449 info.addPatternReco(newInfo);
1450
1451 Trk::Track* newTrack = new Trk::Track(info, std::move(vecTsos),nullptr);
1452
1453 return newTrack;
1454
1455}
1456
1457//==========================================================================================
1459 Trk::ClusterSplitProbabilityContainer &splitProbContainer) const
1460{
1461
1462 for (unsigned int index(0); index < tsosDetails.m_nTSoS; ++index ){
1463 //Only consider split shared hits
1464 if (tsosDetails.m_type[index] != SplitSharedHit)
1465 continue;
1466
1467 // And the hit is a pixel hit
1468 if (tsosDetails.m_detType[index]%10 == 1){
1469 if (const auto * pThisPrd(tsosDetails.m_RIO[index]->prepRawData());pThisPrd->type(Trk::PrepRawDataType::PixelCluster)){
1470 const InDet::PixelCluster* pixelCluster = static_cast<const InDet::PixelCluster*> ( pThisPrd );
1471 Trk::ClusterSplitProbabilityContainer::ProbabilityInfo *splitProb = splitProbContainer.getSplitProbability(pixelCluster);
1472 if (!splitProb) {
1473 splitProb = &(splitProbContainer.setSplitInformation(pixelCluster,0.f,0.f));
1474 }
1475 splitProb->setSplit(true);
1476 } else {
1477 ATH_MSG_WARNING("Cast of a pixel cluster failed????");
1478 }
1479 }
1480 }
1481}
1482
1483
1484//==========================================================================================
1486{
1487
1488 if ( !ptrTrack->trackParameters()->front() ){ return false; }
1489 // above pT for ROI?
1490 if ( ptrTrack->trackParameters()->front()->pT() < m_minPtBjetROI ) { return false; }
1491
1492 return isHadCaloCompatible(*ptrTrack->trackParameters()->front());
1493}
1494
1496{
1498 if (!calo.isValid()) {
1499 ATH_MSG_ERROR("Failed to get Had Calo cluster collection " << m_inputHadClusterContainerName );
1500 return false;
1501 }
1502
1503 return calo->hasMatchingROI(Tp.momentum().phi(), Tp.eta(), 0. /* ignore r of Tp*/, Tp.position().z(), m_phiWidth, m_etaWidth);
1504}
1505
1506//==========================================================================================
1508{
1510 if (!calo.isValid()) {
1511 ATH_MSG_ERROR("Failed to get EM cluster container " << m_inputEmClusterContainerName);
1512 return false;
1513 }
1514 return calo->hasMatchingROI(Tp.momentum().phi(), Tp.momentum().eta(), Tp.position().perp(), Tp.position().z(), m_phiWidthEm, m_etaWidthEm);
1515}
1516
1517
1518
1519std::pair<const Trk::TrackParameters*, const Trk::TrackParameters*>
1521 const Trk::Track* track2,
1522 const Trk::PRDtoTrackMap &prd_to_track_map,
1523 int splitSharedPix ) const
1524{
1525
1526 auto returnPair = std::make_pair<const Trk::TrackParameters*,const Trk::TrackParameters*>(0,0);
1527
1528 //
1529 // Get the TSOS in question from the candidate track since we know which one it is (index)
1530 // Do some basic checks
1531 //
1532 const Trk::TrackStates* track1tsos = track1->trackStateOnSurfaces();
1533
1534 auto firstTsos = track1tsos->begin();
1535 firstTsos += index;
1536 const auto *firstMeas = (*firstTsos)->measurementOnTrack();
1537
1538 if (!firstMeas){
1539 ATH_MSG_ERROR("This is not a measurement!");
1540 return returnPair;
1541 }
1542
1543 if (not firstMeas->type(Trk::MeasurementBaseType::RIO_OnTrack)) {
1544 ATH_MSG_DEBUG("This measurement is not a ROT");
1545 return returnPair;
1546 }
1547
1548 const auto *firstRot = static_cast <const Trk::RIO_OnTrack*> (firstMeas);
1549 if ( !prd_to_track_map.isUsed(*(firstRot->prepRawData()))){
1550 ATH_MSG_ERROR("This hist is not shared");
1551 return returnPair;
1552 }
1553
1554
1555 //
1556 // now, get TSOS from 2nd track which is the one already accepted
1557 // we know it was fitted so this should be possible
1558 const Trk::TrackStates* track2tsos = track2->trackStateOnSurfaces();
1559
1560 auto iTsos = track2tsos->begin();
1561 auto iTsosEnd = track2tsos->end();
1562 int measurementsBeforeShared = 0;
1563 for (; iTsos != iTsosEnd ; ++iTsos) {
1564
1565 // only compare to number of split hits? Why not shared also for NN inefficienicies
1566 if (measurementsBeforeShared > 1 + splitSharedPix ){
1567 ATH_MSG_DEBUG("Too many hits to before shared hit -- unlikely they are from the same thing");
1568 return returnPair;
1569 }
1570
1571 // get measurment from TSOS
1572 const auto *meas = (*iTsos)->measurementOnTrack();
1573
1574 // if we do not have a measurement, we should just mark it
1575 if (!meas) {
1576 continue;
1577 }
1578
1579
1580 if (not meas->type(Trk::MeasurementBaseType::RIO_OnTrack)) {
1581 continue;
1582 }
1583 const Trk::RIO_OnTrack* rot = static_cast <const Trk::RIO_OnTrack*> (meas);
1584 if (rot->prepRawData() != firstRot->prepRawData()){
1585 ++measurementsBeforeShared;
1586 continue;
1587 }
1588
1589 if (!(*iTsos)->trackParameters()){
1590 ATH_MSG_DEBUG("There are no TrackParameters on this TSOS");
1591 return returnPair;
1592 }
1593
1594 returnPair.second = (*iTsos)->trackParameters();
1595 ATH_MSG_DEBUG("Success! track parameters for accepted track " << returnPair.second );
1596 break;
1597 }
1598
1599
1600 //
1601 // Now let's see if we have TPs for the candidate track
1602 //
1603
1604 if (!(*firstTsos)->trackParameters()){
1605 ATH_MSG_DEBUG("There are no TrackParameters on this TSOS");
1606 return returnPair;
1607 }
1608
1609 returnPair.first = (*firstTsos)->trackParameters();
1610
1611
1612 ATH_MSG_DEBUG("Success! track parameters for both tracks " << returnPair.first<< " " << returnPair.second );
1613
1614 return returnPair;
1615
1616}
1617
1618
1619//============================================================================================
1620//
1621inline bool InDet::InDetDenseEnvAmbiTrackSelectionTool::clusCanBeSplit(float splitProb1, float splitProb2) const
1622{
1623 return ( isTwoPartClus(splitProb1, splitProb2) || isMultiPartClus(splitProb2) );
1624}
1625inline bool InDet::InDetDenseEnvAmbiTrackSelectionTool::isTwoPartClus(float splitProb1, float splitProb2) const
1626{
1627 return ( (splitProb1 >= m_sharedProbCut) && (splitProb2 < m_sharedProbCut2) );
1628}
1630{
1631 return ( splitProb2 >= m_sharedProbCut2 );
1632}
1633//============================================================================================
1634//
1635//============================================================================================
1637 TSoS_Details& tsosDetails, int index) {
1638 trackHitDetails.m_trkCouldBeAccepted = false; // we have to remove at least one PRD
1639 tsosDetails.m_type[index] = RejectedHitOverUse;
1640}
1642 TSoS_Details& tsosDetails, int index) {
1643 trackHitDetails.m_trkCouldBeAccepted = false; // we have to remove at least one PRD
1644 tsosDetails.m_type[index] = RejectedHit;
1645}
1646// used after counters have been set
1648 TSoS_Details& tsosDetails, int index) {
1649 rejectHit(trackHitDetails, tsosDetails, index); // reject
1650 decreaseSharedHitCounters( trackHitDetails,
1651 (tsosDetails.m_detType[index]%10 == 1),
1652 (tsosDetails.m_detType[index]%10 == 2) );
1653}
1654// used after counters have been set
1656 TSoS_Details& tsosDetails, int index) {
1657 trackHitDetails.m_trkCouldBeAccepted = false;
1658 tsosDetails.m_type[index] = RejectedHitInvalid; // do not use rejectHit function since use this flag
1659 decreaseSharedHitCounters( trackHitDetails,
1660 (tsosDetails.m_detType[index]%10 == 1),
1661 (tsosDetails.m_detType[index]%10 == 2) );
1662}
1663// used after counters have been set
1665 TSoS_Details& tsosDetails, int index) {
1666 // from shared
1667 decreaseSharedHitCounters( trackHitDetails, true, false ); // isPix=true
1668 // to split
1669 tsosDetails.m_type[index] = SplitSharedHit;
1670 trackHitDetails.m_numSplitSharedPix++;
1671}
1673 TSoS_Details& tsosDetails, int index) {
1674 tsosDetails.m_type[index] = SharedHit;
1675 increaseSharedHitCounters( trackHitDetails, (tsosDetails.m_detType[index]%10 == 1), (tsosDetails.m_detType[index]%10 == 2) );
1676}
1678 trackHitDetails.m_numShared++; // increase counter
1679 trackHitDetails.m_numWeightedShared += (isPix ? 2 : 1); // increase counter
1680 // protect from TRT hits (needed?)
1681 if( isSCT ) { trackHitDetails.m_numSCT_Shared++; }
1682 }
1684 trackHitDetails.m_numShared--; // decrease counter
1685 trackHitDetails.m_numWeightedShared -= (isPix ? 2 : 1); // increase counter
1686 // protect from TRT hits (needed?)
1687 if( isSCT ) { trackHitDetails.m_numSCT_Shared--; }
1688 }
1689//============================================================================================
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
An STL vector of pointers that by default owns its pointed-to elements.
static Double_t Tp(Double_t *t, Double_t *par)
bool isIBL(uint32_t robId)
This is an Identifier helper class for both the Pixel and SCT subdetectors.
Define macros for attributes used to control the static checker.
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
bool isEmCaloCompatible(const Trk::TrackParameters &Tp) const
Check if the cluster is compatible with a EM cluster.
static void rejectSharedHitInvalid(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
bool checkOtherTracksValidity(TSoS_Details &tsosDetails, int index, Trk::ClusterSplitProbabilityContainer &splitProbContainer, Trk::PRDtoTrackMap &prd_to_track_map, int &maxiShared, int &maxOtherNPixel, bool &maxOtherHasIBL, CacheEntry *ent) const
Returns true if accepted tracks remain about thresholds, false otherwise maxiShared = max number of s...
InDetDenseEnvAmbiTrackSelectionTool(const std::string &, const std::string &, const IInterface *)
void setPixelClusterSplitInformation(TSoS_Details &tsosDetails, Trk::ClusterSplitProbabilityContainer &clusterSplitProbMap) const
Update the pixel clusters split information.
SG::ReadHandleKey< ROIPhiRZContainer > m_inputHadClusterContainerName
virtual std::tuple< Trk::Track *, bool > getCleanedOutTrack(const Trk::Track *track, const Trk::TrackScore score, Trk::ClusterSplitProbabilityContainer &splitProbContainer, Trk::PRDtoTrackMap &prd_to_track_map, int trackId, int subtrackId) const override
Decide what to do with a candidate track.
bool isHadCaloCompatible(const Trk::TrackParameters &Tp) const
Check if the cluster is compatible with a hadronic cluster.
static void rejectHit(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
static void rejectSharedHit(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
bool inHadronicROI(const Trk::Track *ptrTrack) const
Does track pass criteria for hadronic ROI?
bool clusCanBeSplit(float splitProb1, float splitProb2) const
Simple helper functions to tell is cluster is split.
void updateSharedForCollimated(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails) const
Handle update of the shared hit counts if either a conversion or a dense hadronic decay was identifie...
SG::ReadHandleKey< ROIPhiRZContainer > m_inputEmClusterContainerName
bool isTwoPartClus(float splitProb1, float splitProb2) const
static void sharedToSplitPix(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
ServiceHandle< IInDetEtaDependentCutsSvc > m_etaDependentCutsSvc
ITk eta-dependet cuts.
static void newEvent(CacheEntry *ent)
Fill hadronic & EM cluster map.
PublicToolHandle< Trk::ITrkObserverTool > m_observerTool
Observer tool This tool is used to observe the tracks and their 'score'.
PublicToolHandle< ITrtDriftCircleCutTool > m_selectortool
TRT minimum number of drift circles tool- returns allowed minimum number of TRT drift circles.
bool performConversionCheck(const Trk::Track *ptrTrack, Trk::PRDtoTrackMap &prd_to_track_map, TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails) const
Specific logic for identifing conversions with the goal of passing those tracks through to the final ...
std::pair< const Trk::TrackParameters *, const Trk::TrackParameters * > getOverlapTrackParameters(int n, const Trk::Track *track1, const Trk::Track *track2, const Trk::PRDtoTrackMap &prd_to_track_map, int splitSharedPix) const
Returns the Trackparameters of the two tracks on the n'th TrackStateOnSurface of the first track.
bool performHadDecayCheck(const Trk::Track *ptrTrack, Trk::PRDtoTrackMap &prd_to_track_map, TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails) const
Specific logic for identifing boosted light particle decays in jet topologies (tau and b),...
static void addSharedHit(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
void fillTrackDetails(const Trk::Track *ptrTrack, Trk::ClusterSplitProbabilityContainer &splitProbContainer, const Trk::PRDtoTrackMap &prd_to_track_map, TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails) const
Fill the two structs TrackHitDetails & TSoS_Details full of information.
static void increaseSharedHitCounters(TrackHitDetails &trackHitDetails, bool isPix, bool isSCT)
Trk::Track * createSubTrack(const std::vector< const Trk::TrackStateOnSurface * > &tsos, const Trk::Track *track) const
method to create a new track from a vector of TSOS's
virtual StatusCode initialize() override
standard Athena-Algorithm method
static void rejectHitOverUse(TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, int index)
static void decreaseSharedHitCounters(TrackHitDetails &trackHitDetails, bool isPix, bool isSCT)
void decideWhichHitsToKeep(const Trk::Track *, const Trk::TrackScore score, Trk::ClusterSplitProbabilityContainer &splitProbContainer, Trk::PRDtoTrackMap &prd_to_track_map, TrackHitDetails &trackHitDetails, TSoS_Details &tsosDetails, CacheEntry *ent, int trackId) const
Determine which hits to keep on this track Look at the hits on track and decided if they should be ke...
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Container to associate Cluster with cluster splitting probabilities.
ProbabilityInfo & setSplitInformation(const PrepRawData *cluster, float prob1, float prob2)
const ProbabilityInfo & splitProbability(const PrepRawData *cluster) const
ProbabilityInfo * getSplitProbability(const PrepRawData *cluster)
int numberDoF() const
returns the number of degrees of freedom of the overall track or vertex fit as integer
Definition FitQuality.h:60
double chiSquared() const
returns the of the overall track fit
Definition FitQuality.h:56
This class is the pure abstract base class for all fittable tracking measurements.
virtual bool type(MeasurementBaseType::Type type) const =0
Interface method checking the type.
bool isUsed(const PrepRawData &prd) const
does this PRD belong to at least one track?
PrepRawDataTrackMapRange onTracks(const PrepRawData &prd)
get the Tracks associated with this PrepRawData.
std::pair< PrepRawDataTrackMap::const_iterator, PrepRawDataTrackMap::const_iterator > ConstPrepRawDataTrackMapRange
bool isShared(const PrepRawData &prd) const
does this PRD belong to more than one track?
virtual bool type(PrepRawDataType type) const
Interface method checking the type.
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
Identifier identify() const
return the identifier -extends MeasurementBase
Contains information about the 'fitter' of this track.
void addPatternReco(const TrackInfo &)
A method adding just pattern recognition info without adding the actual properties.
void setPatternRecognitionInfo(const TrackPatternRecoInfo &patternReco)
Method setting the pattern recognition algorithm.
@ InDetAmbiTrackSelectionTool
Added because of compilation problems.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
A summary of the information contained by a track.
int get(const SummaryType &type) const
returns the summary information for the passed SummaryType.
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
const DataVector< const TrackParameters > * trackParameters() const
Return a pointer to a vector of TrackParameters.
const TrackInfo & info() const
Returns a const ref to info of a const tracks.
const Perigee * perigeeParameters() const
return Perigee.
const Trk::TrackSummary * trackSummary() const
Returns a pointer to the const Trk::TrackSummary owned by this const track (could be nullptr).
const FitQuality * fitQuality() const
return a pointer to the fit quality const-overload
float TrackScore
Definition TrackScore.h:10
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersBase< TrackParametersDim, Charged > TrackParameters
@ numberOfPixelHits
number of pixel layers on track with absence of hits
@ numberOfSCTHoles
number of Holes in both sides of a SCT module
@ numberOfPixelHoles
number of pixels which have a ganged ambiguity.
@ numberOfPixelDeadSensors
number of pixel hits with broad errors (width/sqrt(12))
Definition index.py:1
@ decideWhichHitsToKeep
@ pixelSplitButTooManyShared3Ptc
@ pixelSplitButTooManyShared2Ptc
@ tooManySharedNonRecoverable
@ failedSubtrackCreation
@ firstHitSharedAndPixIBL
@ sharedHitsNotEnoughUniqueHits
@ firstHitSharedAndExtraShared
@ subtrackCreatedWithRecoveredShared
@ sharedIBLSharedWithNoIBLTrack
@ notEnoughUniqueSiHits
@ sharedPixelSharedWithDifferentIBLTrack
@ tooManySharedAfterIncreasingShared
@ tooManySharedRecoverable
@ sharedHitsNotEnoughUniqueSiHits
std::multimap< const Trk::Track *, int, lessTrkTrack > m_overlappingTracks