ATLAS Offline Software
Loading...
Searching...
No Matches
InDetTrackHoleSearchTool.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// InDetTrackHoleSearchTool.cxx, (c) ATLAS Detector software
8
10
11//Trk
12#include "TrkTrack/Track.h"
21#include "Identifier/Identifier.h"
25#include "TrkVolumes/Volume.h"
28
29#include <memory>
30#include <set>
31
32//================ Constructor =================================================
34 const std::string& n,
35 const IInterface* p) :
36 AthAlgTool(t,n,p),
37 m_atlasId(nullptr),
38 m_warning(0) {
39 declareInterface<ITrackHoleSearchTool>(this);
40}
41
42//================ Destructor =================================================
44
45//================ Initialisation =================================================
47
48 StatusCode sc = AlgTool::initialize();
49 if (sc.isFailure()) return sc;
50
51 ATH_CHECK(detStore()->retrieve(m_atlasId, "AtlasID"));
52
53 ATH_CHECK(m_extrapolator.retrieve());
54
55 if (m_extendedListOfHoles) ATH_MSG_INFO("Search for extended list of holes ");
56
57 return StatusCode::SUCCESS;
58}
59
60//================ Finalisation =================================================
62 StatusCode sc = AlgTool::finalize();
63 return sc;
64}
65
66//============================================================================================
68 std::vector<int>& information,
69 const Trk::ParticleHypothesis partHyp) const {
70 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles = nullptr;
71 searchForHoles(track,&information,listOfHoles,partHyp);
72 //listOfHoles _must_ be nullptr
73 }
74
75//============================================================================================
77 const Trk::ParticleHypothesis partHyp) const {
78 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles = new std::vector<const Trk::TrackStateOnSurface*>;
79 searchForHoles(track, nullptr, listOfHoles,partHyp);
80
82 for (const auto *listOfHole : *listOfHoles)
83 output->push_back(listOfHole);
84
85 delete listOfHoles;
86 listOfHoles = nullptr;
87 return output;
88}
89
90//============================================================================================
92 const Trk::ParticleHypothesis partHyp) const {
93 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles = new std::vector<const Trk::TrackStateOnSurface*>;
94 searchForHoles(track, nullptr, listOfHoles,partHyp);
95 const Trk::Track* newTrack = addHolesToTrack(track,listOfHoles);
96 delete listOfHoles;
97 listOfHoles = nullptr;
98 return newTrack;
99}
100
101//============================================================================================
103 const Trk::ParticleHypothesis partHyp) const {
104 return getTrackWithHoles(track,partHyp);
105}
106
107
108//============================================================================================
109
111 std::vector<int>* information,
112 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles,
113 const Trk::ParticleHypothesis partHyp) const {
114 ATH_MSG_DEBUG("starting searchForHoles()");
115
116 if (information) {
117 (*information)[Trk::numberOfPixelHoles] = -1;
118 (*information)[Trk::numberOfSCTHoles] = -1;
119 (*information)[Trk::numberOfSCTDoubleHoles] = -1;
120 (*information)[Trk::numberOfPixelDeadSensors] = -1;
121 (*information)[Trk::numberOfSCTDeadSensors] = -1;
122 (*information)[Trk::numberOfTRTHoles] = -1;
123 (*information)[Trk::numberOfTRTDeadStraws] = -1;
124
125 }
126
127 std::map<const Identifier, const Trk::TrackStateOnSurface*> mapOfHits;
128
129 // JEF: fix of [bug #44382] Poor Tracking Software Performance without SCT
130 // the mapOfPrediction needs the knowledge weather a holesearch should be carried out
131 // on this identifier or just the search for dead modules
132 // therefore: if the boolean is set to true, a holesearch will be caarried out, otherwise just
133 // the search for dead modules
134 // for identifiers BEFORE the last measurement (and after the first): holesearch will be carried out always
135 // for identifiers AFTER the last measurement (or before the first), we have to distiguish two different scenarios:
136 // 1) extendedListOfHoles==True: a hole search will be carried out for all identifiers
137 // 2) extendedListOfHoles==False (default for collisions): dead modules will be counted after the last
138 // measurement, but no holes
139 std::map<const Identifier, std::pair<const Trk::TrackParameters*,const bool> > mapOfPredictions;
140
141 bool listOk = getMapOfHits(
142 Gaudi::Hive::currentContext(), track, partHyp, mapOfHits, mapOfPredictions);
143
144 if (listOk) {
145 ATH_MSG_DEBUG("Perform stepwise hole search");
146 performHoleSearchStepWise(mapOfHits, mapOfPredictions, information, listOfHoles);
147 } else {
148 ATH_MSG_DEBUG("List of hits not properly obtained, abort hole search.");
149 }
150
151 for (auto & mapOfPrediction : mapOfPredictions) {
152 delete (mapOfPrediction.second).first;
153 (mapOfPrediction.second).first = nullptr;
154 }
155
156 }
157
158// ====================================================================================================================
160 const Trk::Track& track,
161 const Trk::ParticleHypothesis partHyp,
162 std::map<const Identifier, const Trk::TrackStateOnSurface*>& mapOfHits,
163 std::map<const Identifier, std::pair<const Trk::TrackParameters*,const bool> >& mapOfPredictions) const {
164
165 /* find all Si TSOS
166 - all of the above have to have identifiers
167 - keep outliers and holes
168 - mark tracks with TRT
169 - sort into map by identifier
170 */
171 //std::cout << "track: " << track << std::endl;
172 int imeas = 0;
173 const Trk::TrackParameters* firstsipar = nullptr;
174
175 for (const auto *iterTSOS : *track.trackStateOnSurfaces()) {
176 // type of state is measurement, hole or outlier ?
177 if (iterTSOS->type(Trk::TrackStateOnSurface::Measurement) ||
178 iterTSOS->type(Trk::TrackStateOnSurface::Outlier)) {
179 Identifier id ;
180 bool hasID = false;
181 if (iterTSOS->measurementOnTrack() != nullptr
182 && iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement() != nullptr
183 && iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify() != 0) {
184 id = iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify();
185 hasID = true;
186 } else if (iterTSOS->trackParameters() != nullptr
187 && iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement() != nullptr
188 && iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement()->identify() != 0) {
189 id = iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement()->identify();
190 hasID = true;
191 }
192 // copy all Si track states, including the holes and outliers
193 if (hasID && (m_atlasId->is_pixel(id) || m_atlasId->is_sct(id))) {
194 // sort the state according to the id
195 mapOfHits.insert(std::pair<const Identifier, const Trk::TrackStateOnSurface*>(id,iterTSOS));
196 if (!iterTSOS->type(Trk::TrackStateOnSurface::Outlier)) {
197 ++imeas;
198 if (!iterTSOS->trackParameters() && m_warning<10) {
199 m_warning++;
200 ATH_MSG_WARNING("No track parameters available for state of type measurement");
201 ATH_MSG_WARNING("Don't run this tool on slimmed tracks!");
202 if (m_warning==10) ATH_MSG_WARNING("(last message!)");
203 }
204 }
205 // for cosmics: remember parameters of first SI TSOS
206 if (m_cosmic && !firstsipar && iterTSOS->trackParameters()) firstsipar=iterTSOS->trackParameters();
207 if (iterTSOS->trackParameters()) {
208 ATH_MSG_VERBOSE("TSOS pos: " << iterTSOS->trackParameters()->position()
209 << " r: " << sqrt(pow(iterTSOS->trackParameters()->position().x(),2)
210 +pow(iterTSOS->trackParameters()->position().y(),2))
211 << " Si measurement");
212 }
213 } else {
214 if (iterTSOS->trackParameters()) {
215 ATH_MSG_VERBOSE("TSOS pos: " << iterTSOS->trackParameters()->position()
216 << " r: " << sqrt(pow(iterTSOS->trackParameters()->position().x(),2)
217 +pow(iterTSOS->trackParameters()->position().y(),2))
218 << " TRT measurement");
219 }
220 }
221 }
222 }
223
224 ATH_MSG_DEBUG("Number of Si hits + outliers on original track: " << mapOfHits.size() << " , hits only: " << imeas);
225 if ((imeas<m_minSiHits && ! m_extendedListOfHoles) || imeas==0 || (!firstsipar && m_cosmic)) {
226 ATH_MSG_DEBUG("Less than "<< m_minSiHits << " Si measurements " << "on track, abort ID hole search");
227 mapOfHits.clear();
228 return false;
229 }
230
231 // find starting point for 2nd iteration to find predictions
232 std::unique_ptr<const Trk::TrackParameters> startParameters;
233
234 // ------- special logic for cosmics to obtain start point for hole search
235
236 if (m_cosmic) {
237 // retrieve surface, from which hole search should start
238 // retrieve tracking geometry
239 const Trk::TrackingGeometry* trackingGeometry = m_extrapolator->trackingGeometry();
240 // get sct volume
241 const Trk::TrackingVolume* sctVolume = trackingGeometry->trackingVolume("InDet::Detectors::SCT::Barrel");
242 //get BoundarySurface for cylinder between sct and trt
243 const Trk::CylinderSurface* sctCylinder = nullptr;
244 const Trk::Surface* sctSurface= &(sctVolume->boundarySurfaces()[Trk::tubeOuterCover]->surfaceRepresentation());
245 if(sctSurface->type()==Trk::SurfaceType::Cylinder){
246 sctCylinder= static_cast<const Trk::CylinderSurface*> (sctSurface);
247 }
248 if (!sctCylinder) {
249 ATH_MSG_ERROR ("cast to CylinderSurface failed, should never happen !");
250 return false;
251 }
252 // extrapolate track to cylinder; take this as starting point for hole search
253
254 if (firstsipar) {
255 //std::cout << "firstsipar: " << *firstsipar << " pos: " << firstsipar->position() << std::endl;
256 startParameters = m_extrapolator->extrapolate(
257 ctx, *firstsipar, *sctCylinder, Trk::oppositeMomentum, true, partHyp);
258 }
259
260 // if track can't be extrapolated to this cylinder (EC track!), extrapolate to disc outside TRT/SCT EC
261 if (!startParameters) {
262 ATH_MSG_DEBUG("no start parameters on SCT cylinder, try TRT ec disc");
263 // get BoundarySurface for disk which encloses TRT ECs
264 // depending on track origin use neg or pos EC
265 const Trk::DiscSurface* trtDisc=nullptr;
266 // inverse logic: tracks with theta < M_PI/2 have origin in negative EC
267 if (firstsipar->parameters()[Trk::theta] < M_PI/2.) {
268 const Trk::TrackingVolume* trtVolume = trackingGeometry->trackingVolume("InDet::Detectors::TRT::NegativeEndcap");
269 const Trk::Surface* trtSurface = &(trtVolume->boundarySurfaces()[Trk::negativeFaceXY]->surfaceRepresentation());
270 if(trtSurface->type()==Trk::SurfaceType::Disc){
271 trtDisc = static_cast<const Trk::DiscSurface*> (trtSurface);
272 }
273 } else {
274 const Trk::TrackingVolume* trtVolume = trackingGeometry->trackingVolume("InDet::Detectors::TRT::PositiveEndcap");
275 const Trk::Surface* trtSurface = &(trtVolume->boundarySurfaces()[Trk::positiveFaceXY]->surfaceRepresentation());
276 if(trtSurface->type()==Trk::SurfaceType::Disc){
277 trtDisc = static_cast<const Trk::DiscSurface*> (trtSurface);
278 }
279 }
280
281 if (trtDisc) {
282 // extrapolate track to disk
283 startParameters = m_extrapolator->extrapolate(
284 ctx, *firstsipar, *trtDisc, Trk::oppositeMomentum, true, partHyp);
285 }
286 }
287 } else { // no cosmics
288
289 if (track.perigeeParameters()) {
290 startParameters.reset( track.perigeeParameters()->clone());
291 } else if (track.trackParameters()->front()) {
292 ATH_MSG_DEBUG("No perigee, extrapolate to 0,0,0");
293 // go back to perigee
294 startParameters =
295 m_extrapolator->extrapolate(ctx,
296 *(track.trackParameters()->front()),
299 false,
300 partHyp);
301 }
302 }
303
304 if (!startParameters) {
305 ATH_MSG_DEBUG("No start point obtained, hole search not performed.");
306 mapOfHits.clear();
307 return false;
308 }
309
310 bool foundFirst = false;
311 // ME - if we look for an extended list of holes, we take the first module, otherwise we searchfor the first measurment
312 // if we have a cosmics track, we want to get the extended list as well!
314 ATH_MSG_DEBUG("We are looking for an extended list of holes, so add eventual holes before first hits");
315 foundFirst = true;
316 }
317
318 Identifier id(0);
319 const Trk::Surface* surf = nullptr;
320 bool hasID = false;
321
322 // 2nd iteration to find predictions
323 Trk::TrackStates::const_iterator iterTSOS = track.trackStateOnSurfaces()->begin();
324
325 // for cosmics: go to the first si mearsurement on track
326 // for cosmics: add perigee as intermediate state, as the extrapolator does nothing if the starting layer and destination layer are the same
327 if (m_cosmic) {
328 while (iterTSOS!=track.trackStateOnSurfaces()->end()
329 && (!(*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement)
330 || (*iterTSOS)->measurementOnTrack()->associatedSurface().type()!=Trk::SurfaceType::Plane)) {
331 ++iterTSOS;
332 }
333 }
334
335 ATH_MSG_VERBOSE("start position: " << startParameters->position()
336 << " r: " << sqrt(pow(startParameters->position().x(),2)
337 +pow(startParameters->position().y(),2)));
338
339 int measno=0;
340 int nmeas=(int)track.measurementsOnTrack()->size();
341 for (; iterTSOS!=track.trackStateOnSurfaces()->end();++iterTSOS) {
342 const Trk::Perigee *per=nullptr;
343 // type of state is measurement ?
344 if ((*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement) ||
345 (*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier) ||
346 ((*iterTSOS)->type(Trk::TrackStateOnSurface::Perigee) && m_cosmic)) {
347 hasID=false;
348 per=nullptr;
349 const Trk::TrackParameters* tmpParam= (*iterTSOS)->trackParameters();
350 if (m_cosmic && tmpParam) {
352 per=static_cast<const Trk::Perigee*>(tmpParam) ;
353 }
354 }
355 if ((*iterTSOS)->measurementOnTrack() != nullptr
356 && (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement() != nullptr
357 && (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify() != 0) {
358 id = (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify();
359 surf = &(*iterTSOS)->measurementOnTrack()->associatedSurface();
360 hasID = true;
361 } else if ((*iterTSOS)->trackParameters() != nullptr
362 && (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement() != nullptr
363 && (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement()->identify() != 0) {
364 id = (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement()->identify();
365 surf = &((*iterTSOS)->trackParameters()->associatedSurface());
366 hasID = true;
367 } else if (m_cosmic && per) {
368 surf=&((*iterTSOS)->trackParameters()->associatedSurface());
369 }
370
371 // see if this is an Si state !
372 if ((m_cosmic && per) || (hasID && (m_atlasId->is_pixel(id) || m_atlasId->is_sct(id) || m_atlasId->is_trt(id)))) {
373
374 if (m_atlasId->is_trt(id)) ATH_MSG_VERBOSE("Target is TRT, see if we can add something");
375
376 // extrapolate stepwise to this parameter (be careful, sorting might be wrong)
377
378 if(std::abs(startParameters->position().z())>5000.){
379 ATH_MSG_DEBUG("Pathological track parameter well outside of tracking detector");
380 ATH_MSG_DEBUG("Propagator might have issue with this, discarding");
381 ATH_MSG_VERBOSE("dumping track parameters " << *startParameters);
382 continue;
383 }
384
385 std::vector<std::unique_ptr<Trk::TrackParameters> > paramList =
386 m_extrapolator->extrapolateStepwise(ctx,
387 *startParameters,
388 *surf,
390 false, partHyp);
391
392 if (paramList.empty()) {
393 ATH_MSG_VERBOSE("--> Did not manage to extrapolate to surface!!!");
394 continue;
395 }
396
397 ATH_MSG_VERBOSE("Number of parameters in this step: " << paramList.size());
398
399 // loop over the predictons and analyze them
400 for (std::unique_ptr<Trk::TrackParameters>& thisParameters : paramList) {
401 ATH_MSG_VERBOSE("extrapolated pos: " << thisParameters->position() << " r: " <<
402 sqrt(pow(thisParameters->position().x(),2)+pow(thisParameters->position().y(),2)));
403
404 // check if surface has identifer !
405 Identifier id2;
406 if ((thisParameters->associatedSurface()).associatedDetectorElement() != nullptr &&
407 (thisParameters->associatedSurface()).associatedDetectorElement()->identify() != 0) {
408 id2 = (thisParameters->associatedSurface()).associatedDetectorElement()->identify();
409 } else {
410 ATH_MSG_VERBOSE("Surface has no detector element ID, skip it");
411 if(thisParameters->associatedSurface().type()==Trk::SurfaceType::Perigee){
412 startParameters = std::move(thisParameters);
413 }
414 continue;
415 }
416
417 // check if it is Si or Pixel
418 if (!(m_atlasId->is_pixel(id2) || m_atlasId->is_sct(id2))) {
419 ATH_MSG_VERBOSE("Surface is not Pixel or SCT, stop loop over parameters in this step");
420 // for collisions, we want to stop at the first trt measurement; whereas for cosmics not
421 // here we will have trt measurements on the track before the first si measurement!
422 if(thisParameters->associatedSurface().type()==Trk::SurfaceType::Perigee){
423 startParameters = std::move(thisParameters);
424 }
425 if (m_cosmic) continue;
426 else break;
427 }
428
429 // see if this surface is in the list
430 std::map<const Identifier, const Trk::TrackStateOnSurface*>::iterator iTSOS = mapOfHits.find(id2);
431
432 if (iTSOS == mapOfHits.end() && !foundFirst) {
433 ATH_MSG_VERBOSE("Si surface before first Si measurement, skip it and continue");
434 continue;
435 }
436
437 // this is a measurement on the track ?
438 if (iTSOS != mapOfHits.end()) {
439 if (!foundFirst && !(*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier)) {
440 ATH_MSG_VERBOSE("Found first Si measurement !");
441 foundFirst = true;
442 }
443
444 // is this a surface which might have a better prediction ?
445 if (iTSOS->second->trackParameters()) {
446 ATH_MSG_VERBOSE("Found track parameter on Si surface, take it");
447 startParameters.reset( iTSOS->second->trackParameters()->clone());
448 } else {
449 ATH_MSG_VERBOSE("No parameter, take extrapolation");
450 startParameters.reset(thisParameters->clone());
451 }
452 }
453
454 // add surface, test insert !
455 std::pair<const Trk::TrackParameters*,const bool> trackparampair (thisParameters.release(),true);
456 if (mapOfPredictions.insert(std::pair<const Identifier, std::pair<const Trk::TrackParameters*,const bool> >(id2,trackparampair)).second) {
457 ATH_MSG_VERBOSE("Added Si surface to mapOfPredictions");
458 } else {
459 ATH_MSG_VERBOSE("Had this, it is a double, skipped");
460 delete trackparampair.first;
461 trackparampair.first=nullptr;
462 }
463 }
464
465 if (!(m_atlasId->is_pixel(id) || m_atlasId->is_sct(id))) {
466 ATH_MSG_VERBOSE("Target was no longer an Si element, break loop");
467 break;
468 }
469
470 }
471 }
472 if ((*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement) && !(*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier)) measno++;
473 if (measno==nmeas) break; // don't count holes after last measurement, this is done below...
474 }
475
476
477 // if last extrapolation is not TRT:
478 // - if countDeadModulesAfterLastHit (robustness): search for dead modules
479 // - if cosmics or extendedListOfHoles: search for more holes after the last measurement (and also dead modules)
481 ATH_MSG_DEBUG("Search for dead modules after the last Si measurement");
482 if (m_extendedListOfHoles || m_cosmic) ATH_MSG_DEBUG("Search for extended list of holes");
483
484 auto cylinderBounds = std::make_shared<Trk::CylinderVolumeBounds>(560, 2750);
485 // don't delete the cylinderBounds -> it's taken care of by Trk::VOlume (see Trk::SharedObject)
486 Trk::Volume* boundaryVol = new Trk::Volume(nullptr, cylinderBounds);
487 // extrapolate this parameter blindly to search for more Si hits (not very fast, I know)
488
489 std::vector<std::unique_ptr<Trk::TrackParameters> > paramList =
490 m_extrapolator->extrapolateBlindly(ctx,
491 *startParameters,
493 false, partHyp,
494 boundaryVol);
495 if (paramList.empty()) {
496 ATH_MSG_VERBOSE("--> Did not manage to extrapolate to another surface, break loop");
497 } else {
498 ATH_MSG_VERBOSE("Number of parameters in this step: " << paramList.size());
499
500 // loop over the predictions and analyze them
501 for (std::unique_ptr<Trk::TrackParameters>& thisParameter : paramList) {
502 // check if surface has identifer !
503 Identifier id2;
504 if (thisParameter->associatedSurface().associatedDetectorElement() != nullptr &&
505 thisParameter->associatedSurface().associatedDetectorElement()->identify() != 0) {
506 id2 = thisParameter->associatedSurface().associatedDetectorElement()->identify();
507
508 // check if it is Si or Pixel
509 if (!(m_atlasId->is_pixel(id2) || m_atlasId->is_sct(id2))) {
510 ATH_MSG_VERBOSE("Surface is not Pixel or SCT, stop loop over parameters in this step");
511 break;
512 }
513
514 // JEF: bool parameter in trackparampair: flag weather this hit should be considered as hole; if
515 // not, just cound dead modules
516 std::pair<Trk::TrackParameters*, const bool> trackparampair(
517 thisParameter.release(), m_extendedListOfHoles || m_cosmic);
518 if (mapOfPredictions
519 .insert(std::pair<const Identifier, std::pair<const Trk::TrackParameters*, const bool>>(
520 id2, trackparampair))
521 .second) {
522 thisParameter.reset(trackparampair.first->clone());
523 ATH_MSG_VERBOSE("Added Si surface");
524 } else {
525 thisParameter.reset(trackparampair.first);
526 ATH_MSG_VERBOSE("Had this, it is a double, skipped");
527 }
528 } else {
529 ATH_MSG_VERBOSE("Surface has no detector element ID, skip it");
530 }
531
532 // keep going...
533 startParameters = std::move(thisParameter);
534 }
535 }
536
537 // gotta clean up ...
538 delete boundaryVol;
539 boundaryVol = nullptr;
540 //delete cylinderBounds; cylinderBounds = 0; // Till : don't delete this guy, it's deleted already when the boundaryVol gets deleted !
541 }
542
543 ATH_MSG_DEBUG("Number of Predictions found: " << mapOfPredictions.size());
544 return true;
545
546}
547
548//=================================================================================================================
549void InDet::InDetTrackHoleSearchTool::performHoleSearchStepWise(std::map<const Identifier, const Trk::TrackStateOnSurface*>& mapOfHits,
550 std::map<const Identifier, std::pair<const Trk::TrackParameters*, const bool> >& mapOfPredictions,
551 std::vector<int>* information,
552 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles) const {
562
563 // counters to steer first/last Si hit logic
564 unsigned int foundTSOS = 0;
565 int PixelHoles = 0, SctHoles = 0, SctDoubleHoles = 0, PixelDead=0, SctDead=0;
566 std::set<Identifier> SctHoleIds;
567
568 ATH_MSG_DEBUG("Start iteration");
569 ATH_MSG_DEBUG("Number of hits+outliers: " << mapOfHits.size() << " and predicted parameters:" << mapOfPredictions.size());
570
571 for (std::map<const Identifier,std::pair<const Trk::TrackParameters*,const bool> >::const_iterator it = mapOfPredictions.begin();
572 it != mapOfPredictions.end(); ++it) {
573
574 const Trk::TrackParameters* nextParameters = (it->second).first;
575
577
578 // search for this ID in the list
579 std::map<const Identifier, const Trk::TrackStateOnSurface*>::iterator iTSOS = mapOfHits.find(id);
580
581 if (iTSOS == mapOfHits.end()) {
582 switch (m_boundaryCheckTool->boundaryCheck(*nextParameters)) {
584 if (m_atlasId->is_pixel(id)) {
585
586 ATH_MSG_VERBOSE("Found element is a dead pixel module, add it to the list and continue");
587 ++PixelDead;
588 } else if (m_atlasId->is_sct(id)) {
589
590 ATH_MSG_VERBOSE("Found element is a dead SCT module, add it to the list and continue");
591 ++SctDead;
592 }
597 continue;
599 break;
600 }
601
602 // increment tmp counters only if this detElement should be considered for a proper holesearch
603 // this info is the boolean in the (mapOfPredictions->second).second
604 if (((it->second).second)) {
605 if (m_atlasId->is_pixel(id)) {
606 ATH_MSG_VERBOSE("Found element is a Pixel hole, add it to the list and continue");
607 ++PixelHoles;
608 } else if (m_atlasId->is_sct(id)) {
609 ATH_MSG_VERBOSE("Found element is a SCT hole, add it to the list and continue");
610 ++SctHoles;
611
612 // check double sct
613 // obtain backside of SCT module
614 const InDetDD::SiDetectorElement* thisElement =
615 dynamic_cast<const InDetDD::SiDetectorElement *> (nextParameters->associatedSurface().associatedDetectorElement());
616 if (!thisElement) {
617 ATH_MSG_ERROR ("cast to SiDetectorElement failed, should never happen !");
618 continue;
619 }
620
621 const Identifier otherId = thisElement->otherSide()->identify();
622 // loop over holes and look for the other one
623 if (SctHoleIds.find(otherId) != SctHoleIds.end()) {
624 ATH_MSG_VERBOSE("Found an SCT double hole !!!");
625 ++SctDoubleHoles;
626 }
627 // keep this id for double side check
628 SctHoleIds.insert(id);
629
630 }
631 // add to tmp list of holes
632 if (listOfHoles) listOfHoles->push_back(createHoleTSOS(nextParameters));
633 continue;
634 } else {
635 continue;
636 }
637 } // end (iTSOS == mapOfHits.end())
638
639 if (iTSOS->second->type(Trk::TrackStateOnSurface::Outlier)) {
640 ++foundTSOS;
641 ATH_MSG_VERBOSE("Found TSOS is an outlier, not a hole, skip it and continue");
642 // remove this one from the map
643 mapOfHits.erase(iTSOS);
644 continue;
645 }
646
647 if (iTSOS->second->type(Trk::TrackStateOnSurface::Measurement)) {
648 ++foundTSOS;
649 ATH_MSG_VERBOSE("Found TSOS is a measurement, continue");
650 // remove this one from the map
651 mapOfHits.erase(iTSOS);
652 continue;
653 }
654 } // end of loop
655
656 ATH_MSG_DEBUG("==> Total number of holes found: "
657 << PixelHoles << " Pixel holes, "
658 << SctHoles << " Sct holes, "
659 << SctDoubleHoles << " Double holes");
660
661 if (listOfHoles) ATH_MSG_DEBUG("==> Size of listOfHoles: " << listOfHoles->size());
662
663 if (!mapOfHits.empty()) {
664 int ioutliers = 0, imeasurements = 0;
665 for (std::map<const Identifier, const Trk::TrackStateOnSurface*>::const_iterator iter = mapOfHits.begin();
666 iter != mapOfHits.end(); ++iter) {
667 if (iter->second->type(Trk::TrackStateOnSurface::Outlier)) ++ioutliers;
668 else if (iter->second->type(Trk::TrackStateOnSurface::Measurement)) ++imeasurements;
669 else ATH_MSG_ERROR("Found wrong TSOS in map !!!");
670 }
671
672 if (imeasurements > 0) {
673 if (PixelHoles+SctHoles+SctDoubleHoles > 0) {
674 ATH_MSG_DEBUG("Not all measurements found, but holes. Left measurements: "
675 << imeasurements << " outliers: " << ioutliers << " found: " << foundTSOS
676 << " Pixel holes: " << PixelHoles << " Sct holes: " << SctHoles
677 << " Double holes: " << SctDoubleHoles);
678 } else {
679 ATH_MSG_DEBUG("Problem ? Not all measurements found. Left measurements: "
680 << imeasurements << " outliers: " << ioutliers << " found: " << foundTSOS);
681 }
682 }
683 }
684
685 // update information and return
686 if (information) {
687 (*information)[Trk::numberOfPixelHoles] = PixelHoles;
688 (*information)[Trk::numberOfSCTHoles] = SctHoles;
689 (*information)[Trk::numberOfSCTDoubleHoles] = SctDoubleHoles;
690 (*information)[Trk::numberOfPixelDeadSensors] = PixelDead;
691 (*information)[Trk::numberOfSCTDeadSensors] = SctDead;
692 }
693
694 }
695
696// ====================================================================================================================
698 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
699 typePattern.set(Trk::TrackStateOnSurface::Hole);
700 const Trk::TrackStateOnSurface* tsos = new Trk::TrackStateOnSurface(nullptr,trackPar->uniqueClone(),nullptr,typePattern);
701 return tsos;
702}
703
704// ====================================================================================================================
706 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles) const {
707 auto trackTSOS = std::make_unique<Trk::TrackStates>();
708
709 // get states from track
710 for (const auto *it : *oldTrack.trackStateOnSurfaces()) {
711 // veto old holes
712 if (!it->type(Trk::TrackStateOnSurface::Hole)) trackTSOS->push_back(new Trk::TrackStateOnSurface(*it));
713 }
714
715 // if we have no holes on the old track and no holes found by search, then we just copy the track
716 if (oldTrack.trackStateOnSurfaces()->size() == trackTSOS->size() && listOfHoles->empty()) {
717 ATH_MSG_DEBUG("No holes on track, copy input track to new track");
718 // create copy of track
719 const Trk::Track* newTrack = new Trk::Track(
720 oldTrack.info(),
721 std::move(trackTSOS),
722 oldTrack.fitQuality() ? oldTrack.fitQuality()->uniqueClone() : nullptr);
723 return newTrack;
724 }
725
726 // add new holes
727 for (const auto *listOfHole : *listOfHoles) {
728 trackTSOS->push_back(listOfHole);
729 }
730
731 // sort
732 const Trk::TrackParameters* perigee = oldTrack.perigeeParameters();
733 if (!perigee) perigee = (*(oldTrack.trackStateOnSurfaces()->begin()))->trackParameters();
734
735 if (perigee) {
736
738
739 // we always have to sort holes in
740 // if (!is_sorted(trackTSOS->begin(),trackTSOS->end(), CompFunc)) {
741
742 if (fabs(perigee->parameters()[Trk::qOverP]) > 0.002) {
743 /* invest n*(logN)**2 sorting time for lowPt, coping with a possibly
744 not 100% transitive comparison functor.
745 */
746 ATH_MSG_DEBUG("sorting vector with stable_sort ");
747 std::stable_sort(trackTSOS->begin(), trackTSOS->end(), CompFunc);
748 } else {
749 trackTSOS->sort(CompFunc); // respects DV object ownership
750 }
751
752 }
753
754 // create copy of track
755 const Trk::Track* newTrack = new Trk::Track(
756 oldTrack.info(),
757 std::move(trackTSOS),
758 oldTrack.fitQuality() ? oldTrack.fitQuality()->uniqueClone() : nullptr);
759
760 return newTrack;
761}
762
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
static Double_t sc
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
size_type size() const noexcept
Returns the number of elements in the collection.
Class to hold geometrical description of a silicon detector element.
const SiDetectorElement * otherSide() const
Useful for SCT only.
virtual Identifier identify() const override final
identifier of this detector element (inline)
virtual void countHoles(const Trk::Track &track, std::vector< int > &information, const Trk::ParticleHypothesis partHyp=Trk::pion) const
Input : track, partHyp Output: Changes in information This method first calls the method getMapOfHits...
void performHoleSearchStepWise(std::map< const Identifier, const Trk::TrackStateOnSurface * > &mapOfHits, std::map< const Identifier, std::pair< const Trk::TrackParameters *, const bool > > &mapOfPredictions, std::vector< int > *information, std::vector< const Trk::TrackStateOnSurface * > *listOfHoles) const
This method searches for holes in a track.
IntegerProperty m_minSiHits
Min number of hits.
virtual const Trk::Track * getTrackWithHoles(const Trk::Track &track, const Trk::ParticleHypothesis partHyp=Trk::pion) const
Input : track, parthyp Return: A pointer to a new Trk::Track which containes the information of the i...
void searchForHoles(const Trk::Track &track, std::vector< int > *information, std::vector< const Trk::TrackStateOnSurface * > *listOfHoles, const Trk::ParticleHypothesis partHyp=Trk::pion) const
Input : track, parthyp Return: Changes in information and/or listOfHoles The interfacing method to th...
bool getMapOfHits(const EventContext &ctx, const Trk::Track &track, const Trk::ParticleHypothesis partHyp, std::map< const Identifier, const Trk::TrackStateOnSurface * > &mapOfHits, std::map< const Identifier, std::pair< const Trk::TrackParameters *, const bool > > &mapOfPredictions) const
Input: track Output: changes in mapOfHits (filling it) and hasTRT Return value: True if filling was s...
const AtlasDetectorID * m_atlasId
ID pixel helper.
static const Trk::TrackStateOnSurface * createHoleTSOS(const Trk::TrackParameters *trackPar)
This method creates a TSOS to represent a detected hole.
ToolHandle< Trk::IExtrapolator > m_extrapolator
Pointer to Extrapolator AlgTool.
InDetTrackHoleSearchTool(const std::string &, const std::string &, const IInterface *)
BooleanProperty m_extendedListOfHoles
Configure outwards hole search.
const Trk::Track * addHolesToTrack(const Trk::Track &oldTrack, std::vector< const Trk::TrackStateOnSurface * > *listOfHoles) const
This Method creates a new Track from the TSOS of the input track combined with the TSOS from listOfHo...
ToolHandle< Trk::IBoundaryCheckTool > m_boundaryCheckTool
virtual const Trk::TrackStates * getHolesOnTrack(const Trk::Track &track, const Trk::ParticleHypothesis partHyp=Trk::pion) const
Input : track, parthyp Return: A DataVector containing pointers to TrackStateOnSurfaces which each re...
virtual const Trk::Track * getTrackWithHolesAndOutliers(const Trk::Track &track, const Trk::ParticleHypothesis partHyp=Trk::pion) const
Input : track, parthyp Return: A pointer to a new Trk::Track which containes the information of the i...
std::atomic_int m_warning
number of warnings printed when no track parameters available
virtual StatusCode finalize()
standard Athena-Algorithm method
virtual ~InDetTrackHoleSearchTool()
default destructor
virtual StatusCode initialize()
standard Athena-Algorithm method
Class for a CylinderSurface in the ATLAS detector.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
std::unique_ptr< FitQuality > uniqueClone() const
NVI uniqueClone.
const Amg::Vector3D & momentum() const
Access method for the momentum.
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
Class describing the Line to which the Perigee refers to.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
Class providing comparison function, or relational definition, for sorting MeasurementBase objects.
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.
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Hole
A hole on the track - this is defined in the following way.
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
const TrackInfo & info() const
Returns a const ref to info of a const tracks.
const Perigee * perigeeParameters() const
return Perigee.
const FitQuality * fitQuality() const
return a pointer to the fit quality const-overload
The TrackingGeometry class is the owner of the constructed TrackingVolumes.
const TrackingVolume * trackingVolume(const std::string &name) const
return the tracking Volume by name, 0 if it doesn't exist
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
virtual Identifier identify() const =0
Identifier.
Base class for all volumes inside the tracking realm, it defines the interface for inherited Volume c...
Definition Volume.h:36
@ oppositeMomentum
@ alongMomentum
@ anyDirection
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ OnEdge
within the sensitive area of an active element
@ DeadElement
outside the element
@ Insensitive
close to the edge of an active element
@ Outside
with the insensitive area of an active element
@ Error
within the nominally active area of a dead element
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
@ numberOfTRTHoles
number of TRT hits which pass the high threshold (only xenon counted) total number of TRT hits which ...
@ 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))
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.