ATLAS Offline Software
Loading...
Searching...
No Matches
CoreStripSpacePointFormationTool.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#include "Acts/Utilities/SpacePointUtility.hpp"
14#include "Acts/SpacePointFormation/SpacePointBuilderConfig.hpp"
18
20namespace ActsTrk
21{
22
23
25
26 ATH_CHECK(detStore()->retrieve(m_stripId, "SCT_ID"));
27 ATH_CHECK(m_lorentzAngleTool.retrieve());
29
31 ATH_MSG_INFO("Use SCT SP overlap cuts based on layer number parity");
32
33 return StatusCode::SUCCESS;
34 }
35
36 StatusCode CoreStripSpacePointFormationTool::produceSpacePoints(const EventContext &ctx,
37 const xAOD::StripClusterContainer &clusterContainer,
38 const InDet::SiElementPropertiesTable &properties,
40 const Amg::Vector3D &beamSpotVertex,
41 std::vector<StripSP>& spacePoints,
42 std::vector<StripSP>& overlapSpacePoints,
43 bool processOverlaps,
44 const std::vector<IdentifierHash>& hashesToProcess,
46 {
51
85
88
89 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
90
92 spBuilderConfig->slSurfaceAccessor.connect<&detail::xAODUncalibMeasSurfAcc::operator()>(&surfaceAccessor);
93 spBuilderConfig->trackingGeometry = m_trackingGeometryTool->trackingGeometry();
94
95
96 auto spConstructor = [this, &clusterContainer, &elements](const Acts::Vector3 &pos,
97 std::optional<double> /*t*/,
98 const Acts::Vector2 &cov,
99 std::optional<double> /*varT*/,
100 const boost::container::static_vector<Acts::SourceLink, 2> &slinks)
101 -> StripSP {
102 std::array<std::size_t,2> measIndices{ std::numeric_limits<std::size_t>::max(), std::numeric_limits<std::size_t>::max()};
103 std::array<StripInformationHelper, 2> stripInfos;
104 size_t idx = 0;
105 for (const auto& slink : slinks){
107 // Check if the cluster is in the cluster container
108 const auto it = std::ranges::find(clusterContainer, dynamic_cast<const xAOD::StripCluster*>(hit));
109 if (it != clusterContainer.end()){
110 const auto cluster_index = std::distance(clusterContainer.begin(), it);
111 const auto id = hit->identifierHash();
112 const auto &element = elements.getDetectorElement(id);
113 size_t stripIndex = 0;
114 auto ends = this->getStripEnds(hit, element, stripIndex);
115 auto vertex = Amg::Vector3D::Zero();
116 StripInformationHelper stripInfo(id,ends.first, ends.second, vertex, ActsTrk::localXFromSourceLink(hit), cluster_index, stripIndex);
117 assert( idx < measIndices.size() && idx < stripInfos.size());
118 measIndices[idx] = cluster_index;
119 stripInfos[idx] = std::move(stripInfo);
120 ++idx;
121 }
122 }
123 const auto& [firstInfo, secondInfo] = stripInfos;
124 const auto topHalfStripLength = 0.5*firstInfo.stripDirection().norm();
125 Eigen::Matrix<double, 3, 1> topStripDirection = -firstInfo.stripDirection()/(2.*topHalfStripLength);
126 Eigen::Matrix<double, 3, 1> topStripCenter = 0.5*firstInfo.trajDirection();
127
128 const auto bottomHalfStripLength = 0.5*secondInfo.stripDirection().norm();
129 Eigen::Matrix<double, 3, 1> bottomStripDirection = -secondInfo.stripDirection()/(2.*bottomHalfStripLength);
130 Eigen::Matrix<double, 3, 1> stripCenterDistance = firstInfo.stripCenter() - secondInfo.stripCenter();
131
132 StripSP sp;
133 sp.idHashes = {firstInfo.idHash(), secondInfo.idHash()};
134 sp.globPos = pos.cast<float>();
135 sp.cov_r = cov(0,0);
136 sp.cov_z = cov(1,0);
137 sp.measurementIndexes = measIndices;
138 sp.topHalfStripLength = topHalfStripLength;
139 sp.bottomHalfStripLength = bottomHalfStripLength;
140 sp.topStripDirection = topStripDirection.cast<float>();
141 sp.bottomStripDirection = bottomStripDirection.cast<float>();
142 sp.stripCenterDistance = stripCenterDistance.cast<float>();
143 sp.topStripCenter = topStripCenter.cast<float>();
144
145 return sp;
146 };
147
148 auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
149
150 const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.allIdentifiers());
151 for (auto &idHash : hashesProc) {
152 const InDetDD::SiDetectorElement *thisElement = elements.getDetectorElement(idHash);
153 if (thisElement->isStereo()) {
154 continue;
155 }
156 // Retrieve the neighbours of the detector element
157 const std::vector<IdentifierHash>& others = *properties.neighbours(idHash);
158
159 if (others.empty()) {
160 continue;
161 }
162 // This flag is use to trigger if the search should be performed.
163 // In case there are no clusters on the neighbours of the selected
164 // detector element, the flag stays false.
165 bool search = false;
166 size_t neighbour = 0;
167 while (not search and neighbour < others.size()){
168 search = stripAccessor.isIdentifierPresent( others.at(neighbour) );
169 neighbour++;
170 }
171 if (not search) {
172 continue;
173 }
174 // prepare clusters, indices and modules for space point formation
175 std::array<std::vector<std::pair<const xAOD::StripCluster *, size_t>>, static_cast<size_t>(nNeighbours)> neighbourClusters{};
176 std::array<std::vector<std::pair<ATLASUncalibSourceLink, size_t>>, static_cast<size_t>(nNeighbours)> neighbourSourceLinks{};
177 std::array<const InDetDD::SiDetectorElement *, static_cast<size_t>(nNeighbours)> neighbourElements{};
178
179 auto groupStart = clusterContainer.begin();
180 // Get the detector element and range for the idHash
181 neighbourElements[0] = thisElement;
182 for (auto &this_range : stripAccessor.rangesForIdentifierDirect(idHash)){
183 for (auto start = this_range.first; start != this_range.second; ++start){
184 size_t position = std::distance(groupStart, start);
185 neighbourClusters[0].push_back(std::make_pair(*start, position));
186 if ((*start)->identifierHash() != thisElement->identifyHash()) {
187 throw std::logic_error("Identifier mismatch.");
188 }
189 auto slink = makeATLASUncalibSourceLink(&clusterContainer, (*start)->index());
190 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
191 }
192 }
193
194 Identifier thisId = thisElement->identify();
195
196 // define overlap extends before building space points
197 std::array<double, 14> overlapExtents{};
198 // Default case: you test the opposite element and the overlapping in phi (total 3 elements)
199 int Nmax = 4;
200
201 // In the barrel, test the eta overlaps as well (total 5 elements)
202 if (m_stripId->is_barrel(thisId))
203 Nmax = 6;
204
205 // You can remove all the overlaps if requested.
206 // Here you test only the opposite element
207 if (not processOverlaps)
208 Nmax = 2;
209
210 float hwidth(properties.halfWidth(idHash));
211 int n = 0;
212
213 // The order of the elements in others is such that you first get the opposite element,
214 // the overlapping in phi and then the overlapping in eta
215 // For this reason you need to re-order the indices, since the SiSpacePointMakerTool will process
216 // first the eta overlaps and then the phi ones
217 const std::array<size_t, nNeighbours> neigbourIndices{ThisOne, Opposite, EtaMinus, EtaPlus, PhiMinus, PhiPlus};
218
219 for (const auto &otherHash : others){
220 if (++n == Nmax) break;
221
222 if (not stripAccessor.isIdentifierPresent(otherHash))
223 continue;
224
225 const InDetDD::SiDetectorElement *otherElement = elements.getDetectorElement(otherHash);
226
227 neighbourElements[neigbourIndices[n]] = otherElement;
228 for (auto &this_range : stripAccessor.rangesForIdentifierDirect(otherHash)){
229 for (auto start = this_range.first; start != this_range.second; ++start){
230 size_t position = std::distance(groupStart, start);
231 neighbourClusters[neigbourIndices[n]].push_back(std::make_pair(*start, position));
232 if ((*start)->identifierHash() != otherElement->identifyHash()) {
233 throw std::logic_error("Identifier mismatch.");
234 }
235 auto slink = makeATLASUncalibSourceLink(&clusterContainer, (*start)->index());
236 neighbourSourceLinks[neigbourIndices[n]].emplace_back(std::make_pair(slink, position));
237 }
238 }
239
240 switch (n){
241 case Opposite:
242 {
243 overlapExtents[0] = -m_overlapLimitOpposite;
244 overlapExtents[1] = m_overlapLimitOpposite;
245 break;
246 }
247 case PhiMinus:
248 {
249 overlapExtents[6] = -hwidth;
250 overlapExtents[7] = -hwidth + m_overlapLimitPhi;
251 overlapExtents[8] = hwidth - m_overlapLimitPhi;
252 overlapExtents[9] = hwidth;
253 break;
254 }
255 case PhiPlus:
256 {
257 overlapExtents[10] = hwidth - m_overlapLimitPhi;
258 overlapExtents[11] = hwidth;
259 overlapExtents[12] = -hwidth;
260 overlapExtents[13] = -hwidth + m_overlapLimitPhi;
261 break;
262 }
263 case EtaMinus:
264 {
265 overlapExtents[ 2] = m_overlapLimitEtaMin;
266 overlapExtents[ 3] = m_overlapLimitEtaMax;
267 if (m_useSCTLayerDep_OverlapCuts && (m_stripId->layer_disk(thisId) & 1) != 0) {
268 overlapExtents[2] = -m_overlapLimitEtaMax;
269 overlapExtents[3] = -m_overlapLimitEtaMin;
270 }
271 break;
272 }
273 default:
274 {
275 overlapExtents[ 4] = m_overlapLimitEtaMin;
276 overlapExtents[ 5] = m_overlapLimitEtaMax;
277 if (m_useSCTLayerDep_OverlapCuts && (m_stripId->layer_disk(thisId) & 1) == 0) {
278 overlapExtents[4] = -m_overlapLimitEtaMax;
279 overlapExtents[5] = -m_overlapLimitEtaMin;
280 }
281 break;
282 }
283 }
284 }
285
286 ATH_CHECK( fillSpacePoints(ctx, spBuilder, neighbourElements, neighbourSourceLinks, overlapExtents, beamSpotVertex,
287 spacePoints, overlapSpacePoints) );
288 }
289
290 return StatusCode::SUCCESS;
291 }
292
293 StatusCode CoreStripSpacePointFormationTool::fillSpacePoints(const EventContext &ctx,
294 std::shared_ptr<Acts::SpacePointBuilder<StripSP>> spBuilder,
295 const std::array<const InDetDD::SiDetectorElement *,nNeighbours>& elements,
296 const std::array<std::vector<std::pair<ATLASUncalibSourceLink, size_t>>,nNeighbours>& sourceLinks,
297 const std::array<double, 14>& overlapExtents,
298 const Amg::Vector3D &beamSpotVertex,
299 std::vector<StripSP>& spacePoints,
300 std::vector<StripSP>& overlapSpacePoints ) const
301 {
302 // This function is called once all the needed quantities are collected.
303 // It is used to build space points checking the compatibility of clusters on pairs of detector elements.
304 // Detector elements and cluster collections are elements and clusters, respectively.
305 // [0] is the trigger element
306 // [1] is the opposite element
307 // [2]-[3] are the elements tested for eta overlaps
308 // [4]-[5] are the elements tested for phi overlaps
309 //
310 // To build space points:
311 // - For the opposite element and the ones tested for eta overlaps, you have to check
312 // if clusters are compatible with the local position of the trigger cluster
313 // requiring that the distance between the two clusters in phi is withing a specified range.
314 // - overlapExtents[0], overlapExtents[1] are filled for the opposite element
315 // - overlapExtents[2], overlapExtents[3], overlapExtents[4], overlapExtents[5] are filled for the eta overlapping elements
316 // - For the elements tested for phi overlaps, you have to check
317 // if clusters are compatible with the local position of the trigger cluster.
318 // This needs that the trigger cluster is at the edge of the trigger module
319 // and that the other cluster is on the compatible edge of its module
320 // - overlapExtents[6], overlapExtents[7], overlapExtents[10], overlapExtents[11]
321 // overlapExtents[8], overlapExtents[9], overlapExtents[12], overlapExtents[13] are filled for the phi overlapping elements
322
323
324
325 Acts::Vector3 vertex(beamSpotVertex.x(), beamSpotVertex.y(), beamSpotVertex.z());
326 constexpr int otherSideIndex{1};
327 constexpr int maxEtaIndex{3};
328 std::array<int,nNeighbours - 1> elementIndex{};
329 int nElements = 0;
330
331 // For the nNeighbours sides, fill elementIndex with the indices of the existing elements.
332 // Same the number of elements in nElements to loop on the later on
333 for (int n = 1; n != nNeighbours; ++n) {
334 if (elements[n]){
335 elementIndex[nElements++] = n;
336 }
337 }
338 // return if all detector elements are nullptr
339 if(!nElements) return StatusCode::SUCCESS;
340
341 const InDetDD::SiDetectorElement *triggerElement = elements[0];
342
343 bool isEndcap = triggerElement->isEndcap();
344 std::vector<StripInformationHelper> stripInfos;
345 stripInfos.reserve(sourceLinks[0].size());
346
347 std::vector<ATLASUncalibSourceLink> triggerSlinks;
348 triggerSlinks.reserve(sourceLinks[0].size());
349
350 // loop on all clusters on the trigger detector element and save the related information
351 for (auto &sourceLink_index : sourceLinks[0]){
352 triggerSlinks.emplace_back(sourceLink_index.first);
353 }
354
355 double limit = 1. + m_stripLengthTolerance;
356 double slimit = 0.;
357
358 if (not m_allClusters){
359 // Start processing the opposite side and the eta overlapping elements
360 int n = 0;
361 for (; n < nElements; ++n){
362 int currentIndex = elementIndex[n];
363 if (currentIndex > maxEtaIndex)
364 break;
365
366 // get the detector element and the IdentifierHash
367 const InDetDD::SiDetectorElement *currentElement = elements[currentIndex];
368
369 // retrieve the range
370 double min = overlapExtents[currentIndex * 2 - 2];
371 double max = overlapExtents[currentIndex * 2 - 1];
372
373 size_t minStrip, maxStrip = 0;
374
375 if (m_stripGapParameter != 0.){
376 updateRange(*triggerElement, *currentElement, slimit, min, max);
377 correctPolarRange(triggerElement, min, max, minStrip, maxStrip);
378 }
379
380 StripInformationHelper currentStripInfo;
381 for (auto &sourceLink_index : sourceLinks[currentIndex]){
382 float source_local_x = ActsTrk::localXFromSourceLink( sourceLink_index.first );
383 const auto currentSlink = sourceLink_index.first;
384 for (auto triggerSlink : triggerSlinks){
385
386 double diff = source_local_x - ActsTrk::localXFromSourceLink( triggerSlink );
387 // In negative endcap, local z is opposite of positive endcap
388 // need to invert the difference for proper comparison
389 if( m_stripId->barrel_ec(currentElement->identify())<0 ) diff = -diff;
390
392 continue;
393 if (currentIndex == otherSideIndex){
394 ATH_CHECK( makeSpacePoint(ctx, spacePoints, spBuilder, triggerSlink, currentSlink, triggerElement,
395 currentElement, limit, slimit, vertex));
396
397 } else {
398 ATH_CHECK(makeSpacePoint(ctx, overlapSpacePoints, spBuilder, triggerSlink, currentSlink, triggerElement,
399 currentElement, limit, slimit, vertex));
400 }
401 }
402 }
403 }
404 // process the phi overlapping elements
405 // if possible n starts from 4
406 for (; n < nElements; ++n){
407 int currentIndex = elementIndex[n];
408 const InDetDD::SiDetectorElement *currentElement = elements[currentIndex];
409 double min = overlapExtents[4 * currentIndex - 10];
410 double max = overlapExtents[4 * currentIndex - 9];
411
412 size_t minStrip, maxStrip = 0;
413
414 if (m_stripGapParameter != 0.){
415 updateRange(*triggerElement, *currentElement, slimit, min, max);
416 correctPolarRange(triggerElement, min, max, minStrip, maxStrip);
417 }
418
419 std::vector<ATLASUncalibSourceLink> triggerPhiSlinks;
420 triggerSlinks.reserve(triggerSlinks.size());
421 for (auto triggerSlink : triggerSlinks){
422 auto centralValue = ActsTrk::localXFromSourceLink( triggerSlink );
423 auto minValue = min;
424 auto maxValue = max;
425 if (isEndcap){
426 size_t stripIndex = 0;
427 getStripEnds(triggerSlink, triggerElement, stripIndex);
428 centralValue = stripIndex;
429 minValue = minStrip;
430 maxValue = maxStrip;
431 }
432 if (minValue <= centralValue and centralValue <= maxValue){
433 triggerPhiSlinks.emplace_back(triggerSlink);
434 }
435 }
436 if (triggerPhiSlinks.empty())
437 continue;
438 min = overlapExtents[4 * currentIndex - 8];
439 max = overlapExtents[4 * currentIndex - 7];
440 if (m_stripGapParameter != 0.){
441 updateRange(*triggerElement, *currentElement, slimit, min, max);
442 correctPolarRange(currentElement, min, max, minStrip, maxStrip);
443 }
444
445 for (auto &sourceLink_index : sourceLinks[currentIndex]){
446 const auto currentSlink = sourceLink_index.first;
447
448 size_t currentStripIndex = 0;
449 getStripEnds(currentSlink, currentElement, currentStripIndex);
450 auto centralValue = ActsTrk::localXFromSourceLink( sourceLink_index.first );
451 auto minValue = min;
452 auto maxValue = max;
453 if (isEndcap) {
454 centralValue = currentStripIndex;
455 minValue = minStrip;
456 maxValue = maxStrip;
457 }
458 if (centralValue < minValue or centralValue > maxValue)
459 continue;
460 for (auto &triggerSlink : triggerPhiSlinks) {
461 ATH_CHECK(makeSpacePoint(ctx, overlapSpacePoints, spBuilder, triggerSlink, currentSlink, triggerElement,
462 currentElement, limit, slimit, vertex));
463 }
464 }
465 }
466 return StatusCode::SUCCESS;
467
468 } // not m_allClusters
469
470 for (int n = 0; n != nElements; ++n){
471
472 int currentIndex = elementIndex[n];
473 const InDetDD::SiDetectorElement *currentElement = elements[currentIndex];
474
475 if (m_stripGapParameter != 0.){
476 computeOffset(*triggerElement, *currentElement, slimit);
477 }
478
479 for (auto &sourceLink_index : sourceLinks[currentIndex]){
480 size_t currentStripIndex = 0;
481 getStripEnds(sourceLink_index.first, triggerElement, currentStripIndex);
482 const auto currentSlink = sourceLink_index.first;
483
484 for (auto triggerSlink : triggerSlinks){
485 if (currentIndex == otherSideIndex){
486 ATH_CHECK(makeSpacePoint(ctx, spacePoints, spBuilder, triggerSlink, currentSlink, triggerElement,
487 currentElement, limit, slimit, vertex));
488 }else{
489 ATH_CHECK(makeSpacePoint(ctx, overlapSpacePoints, spBuilder, triggerSlink, currentSlink, triggerElement,
490 currentElement, limit, slimit, vertex));
491 }
492 }
493 }
494 }
495 return StatusCode::SUCCESS;
496 }
497
498
499 StatusCode CoreStripSpacePointFormationTool::makeSpacePoint(const EventContext &ctx,
500 std::vector<StripSP>& collection,
501 std::shared_ptr<Acts::SpacePointBuilder<StripSP>> spBuilder,
502 const ATLASUncalibSourceLink& currentSlink,
503 const ATLASUncalibSourceLink& anotherSlink,
504 const InDetDD::SiDetectorElement *currentElement,
505 const InDetDD::SiDetectorElement *anotherElement,
506 const double limit,
507 const double slimit,
508 const Acts::Vector3& vertex) const
509 {
510
511 auto tgContext = m_trackingGeometryTool->getGeometryContext(ctx).context();
512
513 size_t stripIndex = 0;
514 auto ends1 = getStripEnds(currentSlink, currentElement, stripIndex);
515 auto ends2 = getStripEnds(anotherSlink, anotherElement, stripIndex);
516 std::pair<Acts::Vector3, Acts::Vector3> ends1_acts;
517 std::pair<Acts::Vector3, Acts::Vector3> ends2_acts;
518 ends1_acts.first = ends1.first;
519 ends1_acts.second = ends1.second;
520 ends2_acts.first = ends2.first;
521 ends2_acts.second = ends2.second;
522 auto paramCovAccessor = [&](const Acts::SourceLink &slink) {
523 const auto &atlasSLink = slink.get<ATLASUncalibSourceLink>();
524 const xAOD::UncalibratedMeasurement *measurement = &getUncalibratedMeasurement(atlasSLink);
525 Acts::BoundVector loc = Acts::BoundVector::Zero();
526 Acts::BoundSquareMatrix cov = Acts::BoundMatrix::Zero();
527 switch (measurement->type()) {
529 loc[Acts::eBoundLoc0] = measurement->localPosition<1>()[Trk::locX];
530 cov.topLeftCorner<1, 1>() =
531 measurement->localCovariance<1>().cast<double>();
532 break;
534 loc[Acts::eBoundLoc0] = measurement->localPosition<2>()[Trk::locX];
535 loc[Acts::eBoundLoc1] = measurement->localPosition<2>()[Trk::locY];
536 cov.topLeftCorner<2, 2>() =
537 measurement->localCovariance<2>().cast<double>();
538 break;
539 default:
540 throw std::domain_error(
541 "Can only handle measurement type pixel or strip");
542 }
543 return std::make_pair(loc, cov);
544 };
545 std::vector<Acts::SourceLink> slinks;
546
547 slinks.emplace_back(Acts::SourceLink{currentSlink});
548 slinks.emplace_back(Acts::SourceLink{anotherSlink});
549
550 Acts::SpacePointBuilderOptions spOpt{std::make_pair(ends1_acts, ends2_acts), paramCovAccessor};
551 spOpt.vertex = vertex;
552 spOpt.stripLengthTolerance = limit - 1;
553 spOpt.stripLengthGapTolerance = slimit;
554
555
556 spBuilder->buildSpacePoint(tgContext, slinks, spOpt,
557 std::back_inserter(collection));
558 return StatusCode::SUCCESS;
559 }
560
562 const InDetDD::SiDetectorElement& element2,
563 double& stripLengthGapTolerance) const
564{
565 // Get transformation matrices and center positions of detector elements
566 const Amg::Transform3D& t1 = element1.transform();
567 const Amg::Transform3D& t2 = element2.transform();
568 const Amg::Vector3D& c = element1.center();
569
570 // Check if first element is an annulus
571 bool isAnnulus = (element1.design().shape() == InDetDD::Annulus);
572
573 // Compute x12 and radius of detector element
574 double x12 = t1.linear().col(0).dot(t2.linear().col(0));
575 double r = isAnnulus ? c.perp() : std::sqrt(t1(0, 3) * t1(0, 3) + t1(1, 3) * t1(1, 3));
576
577 // Compute distance between detector elements in the direction of strips
578 Amg::Vector3D dPos = t1.translation() - t2.translation();
579 double s = dPos.dot(t1.linear().col(2));
580
581 // Compute offset distance
582 double dm = (m_stripGapParameter * r) * std::abs(s * x12);
583 double d = isAnnulus ? dm / 0.04 : dm / std::sqrt((1. - x12) * (1. + x12));
584
585 // Adjust offset distance for z-component of transformation matrix
586 const double zComponentTolerance = 0.7;
587 if (std::abs(t1(2, 2)) > zComponentTolerance)
588 d *= (r / std::abs(t1(2, 3)));
589
590 stripLengthGapTolerance = d;
591
592 return dm;
593}
594
596 const InDetDD::SiDetectorElement &element2,
597 double &stripLengthGapTolerance,
598 double &min, double &max) const
599 {
600 double dm = computeOffset(element1, element2, stripLengthGapTolerance);
601 min -= dm;
602 max += dm;
603 }
604
606 double &min,
607 double &max,
608 size_t &minStrip,
609 size_t &maxStrip) const
610 {
611 if (element->isBarrel())
612 return;
613
614 // design for endcap modules
615 const InDetDD::StripStereoAnnulusDesign *design = dynamic_cast<const InDetDD::StripStereoAnnulusDesign *>(&element->design());
616 if (!design){
617 ATH_MSG_FATAL("Invalid strip annulus design for module with identifier/identifierHash " << element->identify() << "/" << element->identifyHash());
618 return;
619 }
620
621 // converting min and max from cartesian reference frame to polar frame
622 auto firstPosition = (design->localPositionOfCell(design->strip1Dim(0, 0)) +
623 design->localPositionOfCell(design->strip1Dim(design->diodesInRow(0) - 1, 0))) *
624 0.5;
625
626 double radius = firstPosition.xEta();
627
628 InDetDD::SiCellId minCellId = element->cellIdOfPosition(InDetDD::SiLocalPosition(radius, min, 0.));
629 InDetDD::SiCellId maxCellId = element->cellIdOfPosition(InDetDD::SiLocalPosition(radius, max, 0.));
630
631 if (not minCellId.isValid())
632 minCellId = InDetDD::SiCellId(0);
633
634 if (not maxCellId.isValid())
635 maxCellId = InDetDD::SiCellId(design->diodesInRow(0) - 1);
636
637 minStrip = minCellId.strip();
638 maxStrip = maxCellId.strip();
639
640 // re-evaluate min and max in polar coordinate
641 min = std::atan2(min, radius);
642 max = std::atan2(max, radius);
643 }
644
645 std::pair<Amg::Vector3D, Amg::Vector3D>
647 const InDetDD::SiDetectorElement *element,
648 size_t &stripIndex) const
649 {
650 const xAOD::UncalibratedMeasurement &measurement = getUncalibratedMeasurement(sourceLink);
651 auto cluster = dynamic_cast<const xAOD::StripCluster *>(&measurement);
652 if(!cluster){
653 ATH_MSG_FATAL("Could not cast UncalibratedMeasurement as StripCluster");
654 return {};
655 }
656 float source_local_x = ActsTrk::localXFromSourceLink( sourceLink );
657 if (element->isEndcap()) {
658 // design for endcap modules
659 const InDetDD::StripStereoAnnulusDesign *design = dynamic_cast<const InDetDD::StripStereoAnnulusDesign *>(&element->design());
660 if (!design){
661 ATH_MSG_FATAL("Invalid strip annulus design for module with identifier/identifierHash " << element->identify() << "/" << element->identifyHash());
662 return {};
663 }
664
665 // calculate phi pitch for evaluating the strip index
666 double phiPitchPhi = design->phiWidth()/design->diodesInRow(0);
667 stripIndex = -std::floor(source_local_x / phiPitchPhi) + design->diodesInRow(0) *0.5 - 0.5;
668
669 std::pair<Amg::Vector3D, Amg::Vector3D > ends = {
670 element->globalPosition(design->stripPosAtR(stripIndex, 0, design->minR())),
671 element->globalPosition(design->stripPosAtR(stripIndex, 0, design->maxR()))
672 };
673 return ends;
674 }
675
676 InDetDD::SiLocalPosition localPosition(0., source_local_x, 0.);
677 std::pair<Amg::Vector3D, Amg::Vector3D> ends(element->endsOfStrip(localPosition));
678 return ends;
679 }
680
681}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define maxValue(current, test)
#define minValue(current, test)
static Double_t sp
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
This is an Identifier helper class for the SCT subdetector.
Handle class for recording to StoreGate.
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
virtual StatusCode produceSpacePoints(const EventContext &ctx, const xAOD::StripClusterContainer &clusterContainer, const InDet::SiElementPropertiesTable &properties, const InDetDD::SiDetectorElementCollection &elements, const Amg::Vector3D &beamSpotVertex, std::vector< StripSP > &spacePoints, std::vector< StripSP > &overlapSpacePoints, bool processOverlaps, const std::vector< IdentifierHash > &hashesToProcess, const ContainerAccessor< xAOD::StripCluster, IdentifierHash, 1 > &stripAccessor) const override
StatusCode fillSpacePoints(const EventContext &ctx, std::shared_ptr< Acts::SpacePointBuilder< StripSP > > spBuilder, const std::array< const InDetDD::SiDetectorElement *, nNeighbours > &neighbourElements, const std::array< std::vector< std::pair< ATLASUncalibSourceLink, size_t > >, nNeighbours > &neighbourSourceLinks, const std::array< double, 14 > &overlapExtents, const Amg::Vector3D &beamSpotVertex, std::vector< StripSP > &spacePoints, std::vector< StripSP > &overlapSpacePoints) const
void updateRange(const InDetDD::SiDetectorElement &element1, const InDetDD::SiDetectorElement &element2, double &stripLengthGapTolerance, double &min, double &max) const
std::pair< Amg::Vector3D, Amg::Vector3D > getStripEnds(const xAOD::StripCluster *cluster, const InDetDD::SiDetectorElement *element, size_t &stripIndex) const
StatusCode makeSpacePoint(const EventContext &ctx, std::vector< StripSP > &collection, std::shared_ptr< Acts::SpacePointBuilder< StripSP > > spBuilder, const ATLASUncalibSourceLink &currentSlink, const ATLASUncalibSourceLink &anotherSlink, const InDetDD::SiDetectorElement *currentElement, const InDetDD::SiDetectorElement *anotherElement, const double limit, const double slimit, const Acts::Vector3 &vertex) const
void correctPolarRange(const InDetDD::SiDetectorElement *element, double &min, double &max, size_t &minStrip, size_t &maxStrip) const
double computeOffset(const InDetDD::SiDetectorElement &element1, const InDetDD::SiDetectorElement &element2, double &stripLengthGapTolerance) const
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
static const xAOD::UncalibratedMeasurement * unpack(const Acts::SourceLink &sl)
Helper method to unpack an Acts source link to an uncalibrated measurement.
Helper class to access the Acts::surface associated with an Uncalibrated xAOD measurement.
Class implementing how to access a container.
const boost::container::small_vector< Range, inline_size > rangesForIdentifierDirect(const identifier_t &identifier) const
Function to return the list of ranges corresponding to a given identifier.
std::vector< identifier_t > allIdentifiers() const
Function to return all available identifier (i.e. keys in the map)
bool isIdentifierPresent(const identifier_t &identifier) const
Function to verify if a given identifier is present in the map, i.e.
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.
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int strip() const
Get strip number. Equivalent to phiIndex().
Definition SiCellId.h:131
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
Class to hold the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
bool isStereo() const
Check if it is the stereo side (useful for SCT)
std::pair< Amg::Vector3D, Amg::Vector3D > endsOfStrip(const Amg::Vector2D &position) const
Special method for SCT to retrieve the two ends of a "strip" Returned coordinates are in global frame...
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual const Amg::Transform3D & transform() const override final
Return local to global transform.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
virtual Identifier identify() const override final
identifier of this detector element (inline)
virtual int strip1Dim(int strip, int row) const override
only relevant for SCT.
SiLocalPosition stripPosAtR(int strip, int row, double r) const
virtual SiLocalPosition localPositionOfCell(const SiCellId &cellId) const override
id -> position
virtual int diodesInRow(const int row) const override
DetectorIDHashType identifierHash() const
Returns the IdentifierHash of the measurement (corresponds to the detector element IdentifierHash)
int r
Definition globals.cxx:22
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition hcg.cxx:739
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
float localXFromSourceLink(const ATLASUncalibSourceLink &source_link)
const xAOD::UncalibratedMeasurement & getUncalibratedMeasurement(const ATLASUncalibSourceLink &source_link)
ATLASUncalibSourceLink makeATLASUncalibSourceLink(const xAOD::UncalibratedMeasurementContainer *container, std::size_t index, const EventContext &ctx)
const xAOD::UncalibratedMeasurement * ATLASUncalibSourceLink
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
StripClusterContainer_v1 StripClusterContainer
Define the version of the strip cluster container.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.