ATLAS Offline Software
Loading...
Searching...
No Matches
InDetTrackHoleSearchTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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 if (listOfHoles) {
73 ATH_MSG_ERROR("listOfHoles is leaking in countHoles !!!");
74 for (const auto *listOfHole : *listOfHoles) {
75 delete listOfHole;
76 }
77 delete listOfHoles;
78 listOfHoles = nullptr;
79 }
80 }
81
82//============================================================================================
84 const Trk::ParticleHypothesis partHyp) const {
85 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles = new std::vector<const Trk::TrackStateOnSurface*>;
86 searchForHoles(track, nullptr, listOfHoles,partHyp);
87
89 for (const auto *listOfHole : *listOfHoles)
90 output->push_back(listOfHole);
91
92 delete listOfHoles;
93 listOfHoles = nullptr;
94 return output;
95}
96
97//============================================================================================
99 const Trk::ParticleHypothesis partHyp) const {
100 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles = new std::vector<const Trk::TrackStateOnSurface*>;
101 searchForHoles(track, nullptr, listOfHoles,partHyp);
102 const Trk::Track* newTrack = addHolesToTrack(track,listOfHoles);
103 delete listOfHoles;
104 listOfHoles = nullptr;
105 return newTrack;
106}
107
108//============================================================================================
110 const Trk::ParticleHypothesis partHyp) const {
111 return getTrackWithHoles(track,partHyp);
112}
113
114
115//============================================================================================
116
118 std::vector<int>* information,
119 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles,
120 const Trk::ParticleHypothesis partHyp) const {
121 ATH_MSG_DEBUG("starting searchForHoles()");
122
123 if (information) {
124 (*information)[Trk::numberOfPixelHoles] = -1;
125 (*information)[Trk::numberOfSCTHoles] = -1;
126 (*information)[Trk::numberOfSCTDoubleHoles] = -1;
127 (*information)[Trk::numberOfPixelDeadSensors] = -1;
128 (*information)[Trk::numberOfSCTDeadSensors] = -1;
129 (*information)[Trk::numberOfTRTHoles] = -1;
130 (*information)[Trk::numberOfTRTDeadStraws] = -1;
131
132 }
133
134 std::map<const Identifier, const Trk::TrackStateOnSurface*> mapOfHits;
135
136 // JEF: fix of [bug #44382] Poor Tracking Software Performance without SCT
137 // the mapOfPrediction needs the knowledge weather a holesearch should be carried out
138 // on this identifier or just the search for dead modules
139 // therefore: if the boolean is set to true, a holesearch will be caarried out, otherwise just
140 // the search for dead modules
141 // for identifiers BEFORE the last measurement (and after the first): holesearch will be carried out always
142 // for identifiers AFTER the last measurement (or before the first), we have to distiguish two different scenarios:
143 // 1) extendedListOfHoles==True: a hole search will be carried out for all identifiers
144 // 2) extendedListOfHoles==False (default for collisions): dead modules will be counted after the last
145 // measurement, but no holes
146 std::map<const Identifier, std::pair<const Trk::TrackParameters*,const bool> > mapOfPredictions;
147
148 bool listOk = getMapOfHits(
149 Gaudi::Hive::currentContext(), track, partHyp, mapOfHits, mapOfPredictions);
150
151 if (listOk) {
152 ATH_MSG_DEBUG("Perform stepwise hole search");
153 performHoleSearchStepWise(mapOfHits, mapOfPredictions, information, listOfHoles);
154 } else {
155 ATH_MSG_DEBUG("List of hits not properly obtained, abort hole search.");
156 }
157
158 for (auto & mapOfPrediction : mapOfPredictions) {
159 delete (mapOfPrediction.second).first;
160 (mapOfPrediction.second).first = nullptr;
161 }
162
163 }
164
165// ====================================================================================================================
167 const Trk::Track& track,
168 const Trk::ParticleHypothesis partHyp,
169 std::map<const Identifier, const Trk::TrackStateOnSurface*>& mapOfHits,
170 std::map<const Identifier, std::pair<const Trk::TrackParameters*,const bool> >& mapOfPredictions) const {
171
172 /* find all Si TSOS
173 - all of the above have to have identifiers
174 - keep outliers and holes
175 - mark tracks with TRT
176 - sort into map by identifier
177 */
178 //std::cout << "track: " << track << std::endl;
179 int imeas = 0;
180 const Trk::TrackParameters* firstsipar = nullptr;
181
182 for (const auto *iterTSOS : *track.trackStateOnSurfaces()) {
183 // type of state is measurement, hole or outlier ?
184 if (iterTSOS->type(Trk::TrackStateOnSurface::Measurement) ||
185 iterTSOS->type(Trk::TrackStateOnSurface::Outlier)) {
186 Identifier id ;
187 bool hasID = false;
188 if (iterTSOS->measurementOnTrack() != nullptr
189 && iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement() != nullptr
190 && iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify() != 0) {
191 id = iterTSOS->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify();
192 hasID = true;
193 } else if (iterTSOS->trackParameters() != nullptr
194 && iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement() != nullptr
195 && iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement()->identify() != 0) {
196 id = iterTSOS->trackParameters()->associatedSurface().associatedDetectorElement()->identify();
197 hasID = true;
198 }
199 // copy all Si track states, including the holes and outliers
200 if (hasID && (m_atlasId->is_pixel(id) || m_atlasId->is_sct(id))) {
201 // sort the state according to the id
202 mapOfHits.insert(std::pair<const Identifier, const Trk::TrackStateOnSurface*>(id,iterTSOS));
203 if (!iterTSOS->type(Trk::TrackStateOnSurface::Outlier)) {
204 ++imeas;
205 if (!iterTSOS->trackParameters() && m_warning<10) {
206 m_warning++;
207 ATH_MSG_WARNING("No track parameters available for state of type measurement");
208 ATH_MSG_WARNING("Don't run this tool on slimmed tracks!");
209 if (m_warning==10) ATH_MSG_WARNING("(last message!)");
210 }
211 }
212 // for cosmics: remember parameters of first SI TSOS
213 if (m_cosmic && !firstsipar && iterTSOS->trackParameters()) firstsipar=iterTSOS->trackParameters();
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 << " Si measurement");
219 }
220 } else {
221 if (iterTSOS->trackParameters()) {
222 ATH_MSG_VERBOSE("TSOS pos: " << iterTSOS->trackParameters()->position()
223 << " r: " << sqrt(pow(iterTSOS->trackParameters()->position().x(),2)
224 +pow(iterTSOS->trackParameters()->position().y(),2))
225 << " TRT measurement");
226 }
227 }
228 }
229 }
230
231 ATH_MSG_DEBUG("Number of Si hits + outliers on original track: " << mapOfHits.size() << " , hits only: " << imeas);
232 if ((imeas<m_minSiHits && ! m_extendedListOfHoles) || imeas==0 || (!firstsipar && m_cosmic)) {
233 ATH_MSG_DEBUG("Less than "<< m_minSiHits << " Si measurements " << "on track, abort ID hole search");
234 mapOfHits.clear();
235 return false;
236 }
237
238 // find starting point for 2nd iteration to find predictions
239 std::unique_ptr<const Trk::TrackParameters> startParameters;
240
241 // ------- special logic for cosmics to obtain start point for hole search
242
243 if (m_cosmic) {
244 // retrieve surface, from which hole search should start
245 // retrieve tracking geometry
246 const Trk::TrackingGeometry* trackingGeometry = m_extrapolator->trackingGeometry();
247 // get sct volume
248 const Trk::TrackingVolume* sctVolume = trackingGeometry->trackingVolume("InDet::Detectors::SCT::Barrel");
249 //get BoundarySurface for cylinder between sct and trt
250 const Trk::CylinderSurface* sctCylinder = nullptr;
251 const Trk::Surface* sctSurface= &(sctVolume->boundarySurfaces()[Trk::tubeOuterCover]->surfaceRepresentation());
252 if(sctSurface->type()==Trk::SurfaceType::Cylinder){
253 sctCylinder= static_cast<const Trk::CylinderSurface*> (sctSurface);
254 }
255 if (!sctCylinder) {
256 ATH_MSG_ERROR ("cast to CylinderSurface failed, should never happen !");
257 return false;
258 }
259 // extrapolate track to cylinder; take this as starting point for hole search
260
261 if (firstsipar) {
262 //std::cout << "firstsipar: " << *firstsipar << " pos: " << firstsipar->position() << std::endl;
263 startParameters = m_extrapolator->extrapolate(
264 ctx, *firstsipar, *sctCylinder, Trk::oppositeMomentum, true, partHyp);
265 }
266
267 // if track can't be extrapolated to this cylinder (EC track!), extrapolate to disc outside TRT/SCT EC
268 if (!startParameters) {
269 ATH_MSG_DEBUG("no start parameters on SCT cylinder, try TRT ec disc");
270 // get BoundarySurface for disk which encloses TRT ECs
271 // depending on track origin use neg or pos EC
272 const Trk::DiscSurface* trtDisc=nullptr;
273 // inverse logic: tracks with theta < M_PI/2 have origin in negative EC
274 if (firstsipar->parameters()[Trk::theta] < M_PI/2.) {
275 const Trk::TrackingVolume* trtVolume = trackingGeometry->trackingVolume("InDet::Detectors::TRT::NegativeEndcap");
276 const Trk::Surface* trtSurface = &(trtVolume->boundarySurfaces()[Trk::negativeFaceXY]->surfaceRepresentation());
277 if(trtSurface->type()==Trk::SurfaceType::Disc){
278 trtDisc = static_cast<const Trk::DiscSurface*> (trtSurface);
279 }
280 } else {
281 const Trk::TrackingVolume* trtVolume = trackingGeometry->trackingVolume("InDet::Detectors::TRT::PositiveEndcap");
282 const Trk::Surface* trtSurface = &(trtVolume->boundarySurfaces()[Trk::positiveFaceXY]->surfaceRepresentation());
283 if(trtSurface->type()==Trk::SurfaceType::Disc){
284 trtDisc = static_cast<const Trk::DiscSurface*> (trtSurface);
285 }
286 }
287
288 if (trtDisc) {
289 // extrapolate track to disk
290 startParameters = m_extrapolator->extrapolate(
291 ctx, *firstsipar, *trtDisc, Trk::oppositeMomentum, true, partHyp);
292 }
293 }
294 } else { // no cosmics
295
296 if (track.perigeeParameters()) {
297 startParameters.reset( track.perigeeParameters()->clone());
298 } else if (track.trackParameters()->front()) {
299 ATH_MSG_DEBUG("No perigee, extrapolate to 0,0,0");
300 // go back to perigee
301 startParameters =
302 m_extrapolator->extrapolate(ctx,
303 *(track.trackParameters()->front()),
306 false,
307 partHyp);
308 }
309 }
310
311 if (!startParameters) {
312 ATH_MSG_DEBUG("No start point obtained, hole search not performed.");
313 mapOfHits.clear();
314 return false;
315 }
316
317 bool foundFirst = false;
318 // ME - if we look for an extended list of holes, we take the first module, otherwise we searchfor the first measurment
319 // if we have a cosmics track, we want to get the extended list as well!
321 ATH_MSG_DEBUG("We are looking for an extended list of holes, so add eventual holes before first hits");
322 foundFirst = true;
323 }
324
325 Identifier id(0);
326 const Trk::Surface* surf = nullptr;
327 bool hasID = false;
328
329 // 2nd iteration to find predictions
330 Trk::TrackStates::const_iterator iterTSOS = track.trackStateOnSurfaces()->begin();
331
332 // for cosmics: go to the first si mearsurement on track
333 // for cosmics: add perigee as intermediate state, as the extrapolator does nothing if the starting layer and destination layer are the same
334 if (m_cosmic) {
335 while (iterTSOS!=track.trackStateOnSurfaces()->end()
336 && (!(*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement)
337 || (*iterTSOS)->measurementOnTrack()->associatedSurface().type()!=Trk::SurfaceType::Plane)) {
338 ++iterTSOS;
339 }
340 }
341
342 ATH_MSG_VERBOSE("start position: " << startParameters->position()
343 << " r: " << sqrt(pow(startParameters->position().x(),2)
344 +pow(startParameters->position().y(),2)));
345
346 int measno=0;
347 int nmeas=(int)track.measurementsOnTrack()->size();
348 for (; iterTSOS!=track.trackStateOnSurfaces()->end();++iterTSOS) {
349 const Trk::Perigee *per=nullptr;
350 // type of state is measurement ?
351 if ((*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement) ||
352 (*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier) ||
353 ((*iterTSOS)->type(Trk::TrackStateOnSurface::Perigee) && m_cosmic)) {
354 hasID=false;
355 per=nullptr;
356 const Trk::TrackParameters* tmpParam= (*iterTSOS)->trackParameters();
357 if (m_cosmic && tmpParam) {
359 per=static_cast<const Trk::Perigee*>(tmpParam) ;
360 }
361 }
362 if ((*iterTSOS)->measurementOnTrack() != nullptr
363 && (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement() != nullptr
364 && (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify() != 0) {
365 id = (*iterTSOS)->measurementOnTrack()->associatedSurface().associatedDetectorElement()->identify();
366 surf = &(*iterTSOS)->measurementOnTrack()->associatedSurface();
367 hasID = true;
368 } else if ((*iterTSOS)->trackParameters() != nullptr
369 && (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement() != nullptr
370 && (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement()->identify() != 0) {
371 id = (*iterTSOS)->trackParameters()->associatedSurface().associatedDetectorElement()->identify();
372 surf = &((*iterTSOS)->trackParameters()->associatedSurface());
373 hasID = true;
374 } else if (m_cosmic && per) {
375 surf=&((*iterTSOS)->trackParameters()->associatedSurface());
376 }
377
378 // see if this is an Si state !
379 if ((m_cosmic && per) || (hasID && (m_atlasId->is_pixel(id) || m_atlasId->is_sct(id) || m_atlasId->is_trt(id)))) {
380
381 if (m_atlasId->is_trt(id)) ATH_MSG_VERBOSE("Target is TRT, see if we can add something");
382
383 // extrapolate stepwise to this parameter (be careful, sorting might be wrong)
384
385 if(std::abs(startParameters->position().z())>5000.){
386 ATH_MSG_DEBUG("Pathological track parameter well outside of tracking detector");
387 ATH_MSG_DEBUG("Propagator might have issue with this, discarding");
388 ATH_MSG_VERBOSE("dumping track parameters " << *startParameters);
389 continue;
390 }
391
392 std::vector<std::unique_ptr<Trk::TrackParameters> > paramList =
393 m_extrapolator->extrapolateStepwise(ctx,
394 *startParameters,
395 *surf,
397 false, partHyp);
398
399 if (paramList.empty()) {
400 ATH_MSG_VERBOSE("--> Did not manage to extrapolate to surface!!!");
401 continue;
402 }
403
404 ATH_MSG_VERBOSE("Number of parameters in this step: " << paramList.size());
405
406 // loop over the predictons and analyze them
407 for (std::unique_ptr<Trk::TrackParameters>& thisParameters : paramList) {
408 ATH_MSG_VERBOSE("extrapolated pos: " << thisParameters->position() << " r: " <<
409 sqrt(pow(thisParameters->position().x(),2)+pow(thisParameters->position().y(),2)));
410
411 // check if surface has identifer !
413 if ((thisParameters->associatedSurface()).associatedDetectorElement() != nullptr &&
414 (thisParameters->associatedSurface()).associatedDetectorElement()->identify() != 0) {
415 id2 = (thisParameters->associatedSurface()).associatedDetectorElement()->identify();
416 } else {
417 ATH_MSG_VERBOSE("Surface has no detector element ID, skip it");
418 if(thisParameters->associatedSurface().type()==Trk::SurfaceType::Perigee){
419 startParameters = std::move(thisParameters);
420 }
421 continue;
422 }
423
424 // check if it is Si or Pixel
425 if (!(m_atlasId->is_pixel(id2) || m_atlasId->is_sct(id2))) {
426 ATH_MSG_VERBOSE("Surface is not Pixel or SCT, stop loop over parameters in this step");
427 // for collisions, we want to stop at the first trt measurement; whereas for cosmics not
428 // here we will have trt measurements on the track before the first si measurement!
429 if(thisParameters->associatedSurface().type()==Trk::SurfaceType::Perigee){
430 startParameters = std::move(thisParameters);
431 }
432 if (m_cosmic) continue;
433 else break;
434 }
435
436 // see if this surface is in the list
437 std::map<const Identifier, const Trk::TrackStateOnSurface*>::iterator iTSOS = mapOfHits.find(id2);
438
439 if (iTSOS == mapOfHits.end() && !foundFirst) {
440 ATH_MSG_VERBOSE("Si surface before first Si measurement, skip it and continue");
441 continue;
442 }
443
444 // this is a measurement on the track ?
445 if (iTSOS != mapOfHits.end()) {
446 if (!foundFirst && !(*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier)) {
447 ATH_MSG_VERBOSE("Found first Si measurement !");
448 foundFirst = true;
449 }
450
451 // is this a surface which might have a better prediction ?
452 if (iTSOS->second->trackParameters()) {
453 ATH_MSG_VERBOSE("Found track parameter on Si surface, take it");
454 startParameters.reset( iTSOS->second->trackParameters()->clone());
455 } else {
456 ATH_MSG_VERBOSE("No parameter, take extrapolation");
457 startParameters.reset(thisParameters->clone());
458 }
459 }
460
461 // add surface, test insert !
462 std::pair<const Trk::TrackParameters*,const bool> trackparampair (thisParameters.release(),true);
463 if (mapOfPredictions.insert(std::pair<const Identifier, std::pair<const Trk::TrackParameters*,const bool> >(id2,trackparampair)).second) {
464 ATH_MSG_VERBOSE("Added Si surface to mapOfPredictions");
465 } else {
466 ATH_MSG_VERBOSE("Had this, it is a double, skipped");
467 delete trackparampair.first;
468 trackparampair.first=nullptr;
469 }
470 }
471
472 if (!(m_atlasId->is_pixel(id) || m_atlasId->is_sct(id))) {
473 ATH_MSG_VERBOSE("Target was no longer an Si element, break loop");
474 break;
475 }
476
477 }
478 }
479 if ((*iterTSOS)->type(Trk::TrackStateOnSurface::Measurement) && !(*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier)) measno++;
480 if (measno==nmeas) break; // don't count holes after last measurement, this is done below...
481 }
482
483
484 // if last extrapolation is not TRT:
485 // - if countDeadModulesAfterLastHit (robustness): search for dead modules
486 // - if cosmics or extendedListOfHoles: search for more holes after the last measurement (and also dead modules)
488 ATH_MSG_DEBUG("Search for dead modules after the last Si measurement");
489 if (m_extendedListOfHoles || m_cosmic) ATH_MSG_DEBUG("Search for extended list of holes");
490
491 auto cylinderBounds = std::make_shared<Trk::CylinderVolumeBounds>(560, 2750);
492 // don't delete the cylinderBounds -> it's taken care of by Trk::VOlume (see Trk::SharedObject)
493 Trk::Volume* boundaryVol = new Trk::Volume(nullptr, cylinderBounds);
494 // extrapolate this parameter blindly to search for more Si hits (not very fast, I know)
495
496 std::vector<std::unique_ptr<Trk::TrackParameters> > paramList =
497 m_extrapolator->extrapolateBlindly(ctx,
498 *startParameters,
500 false, partHyp,
501 boundaryVol);
502 if (paramList.empty()) {
503 ATH_MSG_VERBOSE("--> Did not manage to extrapolate to another surface, break loop");
504 } else {
505 ATH_MSG_VERBOSE("Number of parameters in this step: " << paramList.size());
506
507 // loop over the predictions and analyze them
508 for (std::unique_ptr<Trk::TrackParameters>& thisParameter : paramList) {
509 // check if surface has identifer !
511 if (thisParameter->associatedSurface().associatedDetectorElement() != nullptr &&
512 thisParameter->associatedSurface().associatedDetectorElement()->identify() != 0) {
513 id2 = thisParameter->associatedSurface().associatedDetectorElement()->identify();
514
515 // check if it is Si or Pixel
516 if (!(m_atlasId->is_pixel(id2) || m_atlasId->is_sct(id2))) {
517 ATH_MSG_VERBOSE("Surface is not Pixel or SCT, stop loop over parameters in this step");
518 break;
519 }
520
521 // JEF: bool parameter in trackparampair: flag weather this hit should be considered as hole; if
522 // not, just cound dead modules
523 std::pair<Trk::TrackParameters*, const bool> trackparampair(
524 thisParameter.release(), m_extendedListOfHoles || m_cosmic);
525 if (mapOfPredictions
526 .insert(std::pair<const Identifier, std::pair<const Trk::TrackParameters*, const bool>>(
527 id2, trackparampair))
528 .second) {
529 thisParameter.reset(trackparampair.first->clone());
530 ATH_MSG_VERBOSE("Added Si surface");
531 } else {
532 thisParameter.reset(trackparampair.first);
533 ATH_MSG_VERBOSE("Had this, it is a double, skipped");
534 }
535 } else {
536 ATH_MSG_VERBOSE("Surface has no detector element ID, skip it");
537 }
538
539 // keep going...
540 startParameters = std::move(thisParameter);
541 }
542 }
543
544 // gotta clean up ...
545 delete boundaryVol;
546 boundaryVol = nullptr;
547 //delete cylinderBounds; cylinderBounds = 0; // Till : don't delete this guy, it's deleted already when the boundaryVol gets deleted !
548 }
549
550 ATH_MSG_DEBUG("Number of Predictions found: " << mapOfPredictions.size());
551 return true;
552
553}
554
555//=================================================================================================================
556void InDet::InDetTrackHoleSearchTool::performHoleSearchStepWise(std::map<const Identifier, const Trk::TrackStateOnSurface*>& mapOfHits,
557 std::map<const Identifier, std::pair<const Trk::TrackParameters*, const bool> >& mapOfPredictions,
558 std::vector<int>* information,
559 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles) const {
569
570 // counters to steer first/last Si hit logic
571 unsigned int foundTSOS = 0;
572 int PixelHoles = 0, SctHoles = 0, SctDoubleHoles = 0, PixelDead=0, SctDead=0;
573 std::set<Identifier> SctHoleIds;
574
575 ATH_MSG_DEBUG("Start iteration");
576 ATH_MSG_DEBUG("Number of hits+outliers: " << mapOfHits.size() << " and predicted parameters:" << mapOfPredictions.size());
577
578 for (std::map<const Identifier,std::pair<const Trk::TrackParameters*,const bool> >::const_iterator it = mapOfPredictions.begin();
579 it != mapOfPredictions.end(); ++it) {
580
581 const Trk::TrackParameters* nextParameters = (it->second).first;
582
584
585 // search for this ID in the list
586 std::map<const Identifier, const Trk::TrackStateOnSurface*>::iterator iTSOS = mapOfHits.find(id);
587
588 if (iTSOS == mapOfHits.end()) {
589 switch (m_boundaryCheckTool->boundaryCheck(*nextParameters)) {
591 if (m_atlasId->is_pixel(id)) {
592
593 ATH_MSG_VERBOSE("Found element is a dead pixel module, add it to the list and continue");
594 ++PixelDead;
595 } else if (m_atlasId->is_sct(id)) {
596
597 ATH_MSG_VERBOSE("Found element is a dead SCT module, add it to the list and continue");
598 ++SctDead;
599 }
604 continue;
606 break;
607 }
608
609 // increment tmp counters only if this detElement should be considered for a proper holesearch
610 // this info is the boolean in the (mapOfPredictions->second).second
611 if (((it->second).second)) {
612 if (m_atlasId->is_pixel(id)) {
613 ATH_MSG_VERBOSE("Found element is a Pixel hole, add it to the list and continue");
614 ++PixelHoles;
615 } else if (m_atlasId->is_sct(id)) {
616 ATH_MSG_VERBOSE("Found element is a SCT hole, add it to the list and continue");
617 ++SctHoles;
618
619 // check double sct
620 // obtain backside of SCT module
621 const InDetDD::SiDetectorElement* thisElement =
622 dynamic_cast<const InDetDD::SiDetectorElement *> (nextParameters->associatedSurface().associatedDetectorElement());
623 if (!thisElement) {
624 ATH_MSG_ERROR ("cast to SiDetectorElement failed, should never happen !");
625 continue;
626 }
627
628 const Identifier otherId = thisElement->otherSide()->identify();
629 // loop over holes and look for the other one
630 if (SctHoleIds.find(otherId) != SctHoleIds.end()) {
631 ATH_MSG_VERBOSE("Found an SCT double hole !!!");
632 ++SctDoubleHoles;
633 }
634 // keep this id for double side check
635 SctHoleIds.insert(id);
636
637 }
638 // add to tmp list of holes
639 if (listOfHoles) listOfHoles->push_back(createHoleTSOS(nextParameters));
640 continue;
641 } else {
642 continue;
643 }
644 } // end (iTSOS == mapOfHits.end())
645
646 if (iTSOS->second->type(Trk::TrackStateOnSurface::Outlier)) {
647 ++foundTSOS;
648 ATH_MSG_VERBOSE("Found TSOS is an outlier, not a hole, skip it and continue");
649 // remove this one from the map
650 mapOfHits.erase(iTSOS);
651 continue;
652 }
653
654 if (iTSOS->second->type(Trk::TrackStateOnSurface::Measurement)) {
655 ++foundTSOS;
656 ATH_MSG_VERBOSE("Found TSOS is a measurement, continue");
657 // remove this one from the map
658 mapOfHits.erase(iTSOS);
659 continue;
660 }
661 } // end of loop
662
663 ATH_MSG_DEBUG("==> Total number of holes found: "
664 << PixelHoles << " Pixel holes, "
665 << SctHoles << " Sct holes, "
666 << SctDoubleHoles << " Double holes");
667
668 if (listOfHoles) ATH_MSG_DEBUG("==> Size of listOfHoles: " << listOfHoles->size());
669
670 if (!mapOfHits.empty()) {
671 int ioutliers = 0, imeasurements = 0;
672 for (std::map<const Identifier, const Trk::TrackStateOnSurface*>::const_iterator iter = mapOfHits.begin();
673 iter != mapOfHits.end(); ++iter) {
674 if (iter->second->type(Trk::TrackStateOnSurface::Outlier)) ++ioutliers;
675 else if (iter->second->type(Trk::TrackStateOnSurface::Measurement)) ++imeasurements;
676 else ATH_MSG_ERROR("Found wrong TSOS in map !!!");
677 }
678
679 if (imeasurements > 0) {
680 if (PixelHoles+SctHoles+SctDoubleHoles > 0) {
681 ATH_MSG_DEBUG("Not all measurements found, but holes. Left measurements: "
682 << imeasurements << " outliers: " << ioutliers << " found: " << foundTSOS
683 << " Pixel holes: " << PixelHoles << " Sct holes: " << SctHoles
684 << " Double holes: " << SctDoubleHoles);
685 } else {
686 ATH_MSG_DEBUG("Problem ? Not all measurements found. Left measurements: "
687 << imeasurements << " outliers: " << ioutliers << " found: " << foundTSOS);
688 }
689 }
690 }
691
692 // update information and return
693 if (information) {
694 (*information)[Trk::numberOfPixelHoles] = PixelHoles;
695 (*information)[Trk::numberOfSCTHoles] = SctHoles;
696 (*information)[Trk::numberOfSCTDoubleHoles] = SctDoubleHoles;
697 (*information)[Trk::numberOfPixelDeadSensors] = PixelDead;
698 (*information)[Trk::numberOfSCTDeadSensors] = SctDead;
699 }
700
701 }
702
703// ====================================================================================================================
705 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern;
706 typePattern.set(Trk::TrackStateOnSurface::Hole);
707 const Trk::TrackStateOnSurface* tsos = new Trk::TrackStateOnSurface(nullptr,trackPar->uniqueClone(),nullptr,typePattern);
708 return tsos;
709}
710
711// ====================================================================================================================
713 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles) const {
714 auto trackTSOS = std::make_unique<Trk::TrackStates>();
715
716 // get states from track
717 for (const auto *it : *oldTrack.trackStateOnSurfaces()) {
718 // veto old holes
719 if (!it->type(Trk::TrackStateOnSurface::Hole)) trackTSOS->push_back(new Trk::TrackStateOnSurface(*it));
720 }
721
722 // if we have no holes on the old track and no holes found by search, then we just copy the track
723 if (oldTrack.trackStateOnSurfaces()->size() == trackTSOS->size() && listOfHoles->empty()) {
724 ATH_MSG_DEBUG("No holes on track, copy input track to new track");
725 // create copy of track
726 const Trk::Track* newTrack = new Trk::Track(
727 oldTrack.info(),
728 std::move(trackTSOS),
729 oldTrack.fitQuality() ? oldTrack.fitQuality()->uniqueClone() : nullptr);
730 return newTrack;
731 }
732
733 // add new holes
734 for (const auto *listOfHole : *listOfHoles) {
735 trackTSOS->push_back(listOfHole);
736 }
737
738 // sort
739 const Trk::TrackParameters* perigee = oldTrack.perigeeParameters();
740 if (!perigee) perigee = (*(oldTrack.trackStateOnSurfaces()->begin()))->trackParameters();
741
742 if (perigee) {
743
745
746 // we always have to sort holes in
747 // if (!is_sorted(trackTSOS->begin(),trackTSOS->end(), CompFunc)) {
748
749 if (fabs(perigee->parameters()[Trk::qOverP]) > 0.002) {
750 /* invest n*(logN)**2 sorting time for lowPt, coping with a possibly
751 not 100% transitive comparison functor.
752 */
753 ATH_MSG_DEBUG("sorting vector with stable_sort ");
754 std::stable_sort(trackTSOS->begin(), trackTSOS->end(), CompFunc);
755 } else {
756 trackTSOS->sort(CompFunc); // respects DV object ownership
757 }
758
759 }
760
761 // create copy of track
762 const Trk::Track* newTrack = new Trk::Track(
763 oldTrack.info(),
764 std::move(trackTSOS),
765 oldTrack.fitQuality() ? oldTrack.fitQuality()->uniqueClone() : nullptr);
766
767 return newTrack;
768}
769
#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
HWIdentifier id2
constexpr int pow(int base, int exp) noexcept
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.
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.