ATLAS Offline Software
Loading...
Searching...
No Matches
ActsTrk::CoreStripSpacePointFormationTool Class Reference

Tool to produce strip space points using ACTS SP builder. More...

#include <CoreStripSpacePointFormationTool.h>

Inheritance diagram for ActsTrk::CoreStripSpacePointFormationTool:
Collaboration diagram for ActsTrk::CoreStripSpacePointFormationTool:

Public Member Functions

virtual ~CoreStripSpacePointFormationTool ()=default
virtual StatusCode initialize () override
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

Private Member Functions

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
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 updateRange (const InDetDD::SiDetectorElement &element1, const InDetDD::SiDetectorElement &element2, double &stripLengthGapTolerance, double &min, double &max) const
double computeOffset (const InDetDD::SiDetectorElement &element1, const InDetDD::SiDetectorElement &element2, double &stripLengthGapTolerance) const
void correctPolarRange (const InDetDD::SiDetectorElement *element, double &min, double &max, size_t &minStrip, size_t &maxStrip) const
std::pair< Amg::Vector3D, Amg::Vector3DgetStripEnds (const xAOD::StripCluster *cluster, const InDetDD::SiDetectorElement *element, size_t &stripIndex) const
std::pair< Amg::Vector3D, Amg::Vector3DgetStripEnds (const ATLASUncalibSourceLink &sourceLink, const InDetDD::SiDetectorElement *element, size_t &stripIndex) const

Private Attributes

const SCT_IDm_stripId {}
ToolHandle< ISiLorentzAngleToolm_lorentzAngleTool {this, "LorentzAngleTool", "", "Tool to retreive Lorentz angle of SCT"}
PublicToolHandle< ActsTrk::ITrackingGeometryToolm_trackingGeometryTool {this, "TrackingGeometryTool", ""}
Gaudi::Property< bool > m_allClusters {this, "AllClusters", false, "Process all clusters without limits."}
Gaudi::Property< float > m_overlapLimitOpposite {this, "OverlapLimitOpposite", 2.8, "Overlap limit for opposite-neighbour."}
Gaudi::Property< float > m_overlapLimitPhi {this, "OverlapLimitPhi", 5.64, "Overlap limit for phi-neighbours."}
Gaudi::Property< float > m_overlapLimitEtaMin {this, "OverlapLimitEtaMin", 1.68, "Low overlap limit for eta-neighbours."}
Gaudi::Property< float > m_overlapLimitEtaMax {this, "OverlapLimitEtaMax", 3.0, "High overlap limit for eta-neighbours."}
Gaudi::Property< float > m_stripLengthTolerance {this, "StripLengthTolerance", 0.01}
Gaudi::Property< float > m_stripGapParameter {this, "StripGapParameter", 0.0015, "Recommend 0.001 - 0.0015 for ITK geometry"}
Gaudi::Property< bool > m_useSCTLayerDep_OverlapCuts {this,"useSCTLayerDep_OverlapCuts", true}

Detailed Description

Tool to produce strip space points using ACTS SP builder.

Strip space points are made by combining clusters (obtained from SourceLinks) from pairs of overlapping detectors. The access to overlapping detector elements is possible using the ContainerAccessor. The user can choose just to process the detector element and its opposite on the stereo layer, or also to consider overlaps with the four nearest neighbours of the opposite elements.

Space points are then recorded to storege as StripSP, and then stored as xAOD::SpacePoint in StripSpacePointFormationAlg

Definition at line 37 of file CoreStripSpacePointFormationTool.h.

Constructor & Destructor Documentation

◆ ~CoreStripSpacePointFormationTool()

virtual ActsTrk::CoreStripSpacePointFormationTool::~CoreStripSpacePointFormationTool ( )
virtualdefault

Member Function Documentation

◆ computeOffset()

double ActsTrk::CoreStripSpacePointFormationTool::computeOffset ( const InDetDD::SiDetectorElement & element1,
const InDetDD::SiDetectorElement & element2,
double & stripLengthGapTolerance ) const
private

Definition at line 561 of file CoreStripSpacePointFormationTool.cxx.

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}
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
virtual const Amg::Transform3D & transform() const override final
Return local to global transform.
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
int r
Definition globals.cxx:22
std::vector< ALFA_RawDataContainer_p1 > t2
std::vector< ALFA_RawDataCollection_p1 > t1
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D

◆ correctPolarRange()

void ActsTrk::CoreStripSpacePointFormationTool::correctPolarRange ( const InDetDD::SiDetectorElement * element,
double & min,
double & max,
size_t & minStrip,
size_t & maxStrip ) const
private

Definition at line 605 of file CoreStripSpacePointFormationTool.cxx.

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 }
#define ATH_MSG_FATAL(x)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
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
SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const
As in previous method but returns SiCellId.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
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.
virtual SiLocalPosition localPositionOfCell(const SiCellId &cellId) const override
id -> position
virtual int diodesInRow(const int row) const override

◆ fillSpacePoints()

StatusCode ActsTrk::CoreStripSpacePointFormationTool::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
private

Definition at line 293 of file CoreStripSpacePointFormationTool.cxx.

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;
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;
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 }
#define ATH_CHECK
Evaluate an expression and check for errors.
#define maxValue(current, test)
#define minValue(current, test)
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
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
float localXFromSourceLink(const ATLASUncalibSourceLink &source_link)

◆ getStripEnds() [1/2]

std::pair< Amg::Vector3D, Amg::Vector3D > ActsTrk::CoreStripSpacePointFormationTool::getStripEnds ( const ATLASUncalibSourceLink & sourceLink,
const InDetDD::SiDetectorElement * element,
size_t & stripIndex ) const
private

Definition at line 646 of file CoreStripSpacePointFormationTool.cxx.

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 }
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...
HepGeom::Point3D< double > globalPosition(const HepGeom::Point3D< double > &localPos) const
transform a reconstruction local position into a global position (inline):
SiLocalPosition stripPosAtR(int strip, int row, double r) const
const xAOD::UncalibratedMeasurement & getUncalibratedMeasurement(const ATLASUncalibSourceLink &source_link)
StripCluster_v1 StripCluster
Define the version of the strip cluster class.
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.

◆ getStripEnds() [2/2]

std::pair< Amg::Vector3D, Amg::Vector3D > ActsTrk::CoreStripSpacePointFormationTool::getStripEnds ( const xAOD::StripCluster * cluster,
const InDetDD::SiDetectorElement * element,
size_t & stripIndex ) const
private

◆ initialize()

StatusCode ActsTrk::CoreStripSpacePointFormationTool::initialize ( )
overridevirtual

Definition at line 24 of file CoreStripSpacePointFormationTool.cxx.

24 {
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 }
#define ATH_MSG_INFO(x)
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
retrieve(aClass, aKey=None)
Definition PyKernel.py:110

◆ makeSpacePoint()

StatusCode ActsTrk::CoreStripSpacePointFormationTool::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
private

Definition at line 499 of file CoreStripSpacePointFormationTool.cxx.

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 }
const xAOD::UncalibratedMeasurement * ATLASUncalibSourceLink
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37

◆ produceSpacePoints()

StatusCode ActsTrk::CoreStripSpacePointFormationTool::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
overridevirtual

Production of ActsTrk::SpacePoint from strip clusters Strip space points involves a more complex logic since they are made combining clusters from pairs of overlapping detectors.

For each trigger element, first evaluate and collect the quantities you need to build the space points. The detector element array has capacity 6: [0] is the trigger element [1] is the opposite element [2]-[3] are the elements tested for eta overlaps [4]-[5] are the elements tested for phi overlaps For each element you save the corresponding cluster collections and the space point compatibility range as described below.

For the opposite element and the ones tested for eta overlaps, you have to check if clusters are compatible with the local position of the trigger cluster requiring that the distance between the two clusters in phi is withing a specified range.

  • For the clusters on the opposite element: [-m_overlapLimitOpposite, m_overlapLimitOpposite]
  • For the eta overlapping clusters : you use m_overlapLimitEtaMin and m_overlapLimitEtaMax in different combination depending if you are checking a stereo module or not

For each element, the extremes of these ranges are saved in the overlapExtents array which is used later on

  • overlapExtents[0], overlapExtents[1] are filled for the opposite element
  • overlapExtents[2], overlapExtents[3], overlapExtents[4], overlapExtents[5] are filled for the eta overlapping elements

For the elements tested for phi overlaps, you have to check if clusters are compatible with the local position of the trigger cluster. This needs that the trigger cluster is at the edge of the trigger module: e.g. -hwidth < locX_trigger < -hwidth+m_overlapLimitPhi (or hwidth-m_overlapLimitPhi < locX_trigger < hwidth) and that the other cluster is on the compatible edge of its module: e.g. hwidth-m_overlapLimitPhi < locX_other < hwidth (or -hwidth < locX_other < -hwidth+m_overlapLimitPhi)

For each element, the extremes of these ranges are saved in the overlapExtents array which is used later on

  • overlapExtents[6], overlapExtents[7], overlapExtents[10], overlapExtents[11] overlapExtents[8], overlapExtents[9], overlapExtents[12], overlapExtents[13] are filled for the phi overlapping elements

Access to the cluster from a given detector element is possible via the ContainerAccessor.

Definition at line 36 of file CoreStripSpacePointFormationTool.cxx.

46 {
51
85
88
89 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
90
91 detail::xAODUncalibMeasSurfAcc surfaceAccessor{m_trackingGeometryTool.get()};
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 }
static Double_t sp
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
static const xAOD::UncalibratedMeasurement * unpack(const Acts::SourceLink &sl)
Helper method to unpack an Acts source link to an uncalibrated measurement.
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.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
bool isStereo() const
Check if it is the stereo side (useful for SCT)
DetectorIDHashType identifierHash() const
Returns the IdentifierHash of the measurement (corresponds to the detector element IdentifierHash)
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
ATLASUncalibSourceLink makeATLASUncalibSourceLink(const xAOD::UncalibratedMeasurementContainer *container, std::size_t index, const EventContext &ctx)

◆ updateRange()

void ActsTrk::CoreStripSpacePointFormationTool::updateRange ( const InDetDD::SiDetectorElement & element1,
const InDetDD::SiDetectorElement & element2,
double & stripLengthGapTolerance,
double & min,
double & max ) const
private

Definition at line 595 of file CoreStripSpacePointFormationTool.cxx.

599 {
600 double dm = computeOffset(element1, element2, stripLengthGapTolerance);
601 min -= dm;
602 max += dm;
603 }

Member Data Documentation

◆ m_allClusters

Gaudi::Property<bool> ActsTrk::CoreStripSpacePointFormationTool::m_allClusters {this, "AllClusters", false, "Process all clusters without limits."}
private

Definition at line 100 of file CoreStripSpacePointFormationTool.h.

100{this, "AllClusters", false, "Process all clusters without limits."};

◆ m_lorentzAngleTool

ToolHandle<ISiLorentzAngleTool> ActsTrk::CoreStripSpacePointFormationTool::m_lorentzAngleTool {this, "LorentzAngleTool", "", "Tool to retreive Lorentz angle of SCT"}
private

Definition at line 97 of file CoreStripSpacePointFormationTool.h.

97{this, "LorentzAngleTool", "", "Tool to retreive Lorentz angle of SCT"};

◆ m_overlapLimitEtaMax

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_overlapLimitEtaMax {this, "OverlapLimitEtaMax", 3.0, "High overlap limit for eta-neighbours."}
private

Definition at line 104 of file CoreStripSpacePointFormationTool.h.

104{this, "OverlapLimitEtaMax", 3.0, "High overlap limit for eta-neighbours."};

◆ m_overlapLimitEtaMin

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_overlapLimitEtaMin {this, "OverlapLimitEtaMin", 1.68, "Low overlap limit for eta-neighbours."}
private

Definition at line 103 of file CoreStripSpacePointFormationTool.h.

103{this, "OverlapLimitEtaMin", 1.68, "Low overlap limit for eta-neighbours."};

◆ m_overlapLimitOpposite

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_overlapLimitOpposite {this, "OverlapLimitOpposite", 2.8, "Overlap limit for opposite-neighbour."}
private

Definition at line 101 of file CoreStripSpacePointFormationTool.h.

101{this, "OverlapLimitOpposite", 2.8, "Overlap limit for opposite-neighbour."};

◆ m_overlapLimitPhi

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_overlapLimitPhi {this, "OverlapLimitPhi", 5.64, "Overlap limit for phi-neighbours."}
private

Definition at line 102 of file CoreStripSpacePointFormationTool.h.

102{this, "OverlapLimitPhi", 5.64, "Overlap limit for phi-neighbours."};

◆ m_stripGapParameter

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_stripGapParameter {this, "StripGapParameter", 0.0015, "Recommend 0.001 - 0.0015 for ITK geometry"}
private

Definition at line 106 of file CoreStripSpacePointFormationTool.h.

106{this, "StripGapParameter", 0.0015, "Recommend 0.001 - 0.0015 for ITK geometry"};

◆ m_stripId

const SCT_ID* ActsTrk::CoreStripSpacePointFormationTool::m_stripId {}
private

Definition at line 95 of file CoreStripSpacePointFormationTool.h.

95{};

◆ m_stripLengthTolerance

Gaudi::Property<float> ActsTrk::CoreStripSpacePointFormationTool::m_stripLengthTolerance {this, "StripLengthTolerance", 0.01}
private

Definition at line 105 of file CoreStripSpacePointFormationTool.h.

105{this, "StripLengthTolerance", 0.01};

◆ m_trackingGeometryTool

PublicToolHandle<ActsTrk::ITrackingGeometryTool> ActsTrk::CoreStripSpacePointFormationTool::m_trackingGeometryTool {this, "TrackingGeometryTool", ""}
private

Definition at line 98 of file CoreStripSpacePointFormationTool.h.

98{this, "TrackingGeometryTool", ""};

◆ m_useSCTLayerDep_OverlapCuts

Gaudi::Property< bool > ActsTrk::CoreStripSpacePointFormationTool::m_useSCTLayerDep_OverlapCuts {this,"useSCTLayerDep_OverlapCuts", true}
private

Definition at line 107 of file CoreStripSpacePointFormationTool.h.

107{this,"useSCTLayerDep_OverlapCuts", true};

The documentation for this class was generated from the following files: