6#include "Acts/Utilities/SpacePointUtility.hpp"
14#include "Acts/SpacePointFormation/SpacePointBuilderConfig.hpp"
31 ATH_MSG_INFO(
"Use SCT SP overlap cuts based on layer number parity");
33 return StatusCode::SUCCESS;
41 std::vector<StripSP>& spacePoints,
42 std::vector<StripSP>& overlapSpacePoints,
44 const std::vector<IdentifierHash>& hashesToProcess,
89 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
92 spBuilderConfig->slSurfaceAccessor.connect<&detail::xAODUncalibMeasSurfAcc::operator()>(&surfaceAccessor);
96 auto spConstructor = [
this, &clusterContainer, &elements](
const Acts::Vector3 &pos,
97 std::optional<double> ,
98 const Acts::Vector2 &cov,
99 std::optional<double> ,
100 const boost::container::static_vector<Acts::SourceLink, 2> &slinks)
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;
105 for (
const auto& slink : slinks){
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);
113 size_t stripIndex = 0;
114 auto ends = this->
getStripEnds(hit, element, stripIndex);
115 auto vertex = Amg::Vector3D::Zero();
117 assert( idx < measIndices.size() && idx < stripInfos.size());
118 measIndices[idx] = cluster_index;
119 stripInfos[idx] = std::move(stripInfo);
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();
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();
133 sp.idHashes = {firstInfo.idHash(), secondInfo.idHash()};
134 sp.globPos = pos.cast<
float>();
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>();
148 auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
150 const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.
allIdentifiers());
151 for (
auto &idHash : hashesProc) {
157 const std::vector<IdentifierHash>& others = *properties.neighbours(idHash);
159 if (others.empty()) {
166 size_t neighbour = 0;
167 while (not
search and neighbour < others.size()){
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{};
179 auto groupStart = clusterContainer.
begin();
181 neighbourElements[0] = thisElement;
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.");
190 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
197 std::array<double, 14> overlapExtents{};
207 if (not processOverlaps)
210 float hwidth(properties.halfWidth(idHash));
219 for (
const auto &otherHash : others){
220 if (++n == Nmax)
break;
227 neighbourElements[neigbourIndices[n]] = otherElement;
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.");
236 neighbourSourceLinks[neigbourIndices[n]].emplace_back(std::make_pair(slink, position));
249 overlapExtents[6] = -hwidth;
252 overlapExtents[9] = hwidth;
258 overlapExtents[11] = hwidth;
259 overlapExtents[12] = -hwidth;
287 spacePoints, overlapSpacePoints) );
290 return StatusCode::SUCCESS;
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,
299 std::vector<StripSP>& spacePoints,
300 std::vector<StripSP>& overlapSpacePoints )
const
325 Acts::Vector3 vertex(beamSpotVertex.x(), beamSpotVertex.y(), beamSpotVertex.z());
326 constexpr int otherSideIndex{1};
327 constexpr int maxEtaIndex{3};
335 elementIndex[nElements++] = n;
339 if(!nElements)
return StatusCode::SUCCESS;
343 bool isEndcap = triggerElement->
isEndcap();
344 std::vector<StripInformationHelper> stripInfos;
345 stripInfos.reserve(sourceLinks[0].size());
347 std::vector<ATLASUncalibSourceLink> triggerSlinks;
348 triggerSlinks.reserve(sourceLinks[0].size());
351 for (
auto &sourceLink_index : sourceLinks[0]){
352 triggerSlinks.emplace_back(sourceLink_index.first);
361 for (; n < nElements; ++n){
362 int currentIndex = elementIndex[n];
363 if (currentIndex > maxEtaIndex)
370 double min = overlapExtents[currentIndex * 2 - 2];
371 double max = overlapExtents[currentIndex * 2 - 1];
373 size_t minStrip, maxStrip = 0;
381 for (
auto &sourceLink_index : sourceLinks[currentIndex]){
383 const auto currentSlink = sourceLink_index.first;
384 for (
auto triggerSlink : triggerSlinks){
393 if (currentIndex == otherSideIndex){
395 currentElement, limit, slimit, vertex));
399 currentElement, limit, slimit, vertex));
406 for (; n < nElements; ++n){
407 int currentIndex = elementIndex[n];
409 double min = overlapExtents[4 * currentIndex - 10];
410 double max = overlapExtents[4 * currentIndex - 9];
412 size_t minStrip, maxStrip = 0;
419 std::vector<ATLASUncalibSourceLink> triggerPhiSlinks;
420 triggerSlinks.reserve(triggerSlinks.size());
421 for (
auto triggerSlink : triggerSlinks){
426 size_t stripIndex = 0;
428 centralValue = stripIndex;
433 triggerPhiSlinks.emplace_back(triggerSlink);
436 if (triggerPhiSlinks.empty())
438 min = overlapExtents[4 * currentIndex - 8];
439 max = overlapExtents[4 * currentIndex - 7];
445 for (
auto &sourceLink_index : sourceLinks[currentIndex]){
446 const auto currentSlink = sourceLink_index.first;
448 size_t currentStripIndex = 0;
449 getStripEnds(currentSlink, currentElement, currentStripIndex);
454 centralValue = currentStripIndex;
458 if (centralValue < minValue or centralValue >
maxValue)
460 for (
auto &triggerSlink : triggerPhiSlinks) {
462 currentElement, limit, slimit, vertex));
466 return StatusCode::SUCCESS;
470 for (
int n = 0; n != nElements; ++n){
472 int currentIndex = elementIndex[n];
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;
484 for (
auto triggerSlink : triggerSlinks){
485 if (currentIndex == otherSideIndex){
487 currentElement, limit, slimit, vertex));
490 currentElement, limit, slimit, vertex));
495 return StatusCode::SUCCESS;
500 std::vector<StripSP>& collection,
501 std::shared_ptr<Acts::SpacePointBuilder<StripSP>> spBuilder,
508 const Acts::Vector3& vertex)
const
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) {
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>();
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>();
540 throw std::domain_error(
541 "Can only handle measurement type pixel or strip");
543 return std::make_pair(loc, cov);
545 std::vector<Acts::SourceLink> slinks;
547 slinks.emplace_back(Acts::SourceLink{currentSlink});
548 slinks.emplace_back(Acts::SourceLink{anotherSlink});
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;
556 spBuilder->buildSpacePoint(tgContext, slinks, spOpt,
557 std::back_inserter(collection));
558 return StatusCode::SUCCESS;
563 double& stripLengthGapTolerance)
const
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));
579 double s = dPos.dot(t1.linear().col(2));
583 double d = isAnnulus ? dm / 0.04 : dm / std::sqrt((1. - x12) * (1. + x12));
586 const double zComponentTolerance = 0.7;
587 if (std::abs(t1(2, 2)) > zComponentTolerance)
588 d *= (
r / std::abs(t1(2, 3)));
590 stripLengthGapTolerance = d;
597 double &stripLengthGapTolerance,
598 double &
min,
double &
max)
const
600 double dm =
computeOffset(element1, element2, stripLengthGapTolerance);
609 size_t &maxStrip)
const
626 double radius = firstPosition.xEta();
637 minStrip = minCellId.
strip();
638 maxStrip = maxCellId.
strip();
641 min = std::atan2(
min, radius);
642 max = std::atan2(
max, radius);
645 std::pair<Amg::Vector3D, Amg::Vector3D>
648 size_t &stripIndex)
const
653 ATH_MSG_FATAL(
"Could not cast UncalibratedMeasurement as StripCluster");
667 stripIndex = -std::floor(source_local_x / phiPitchPhi) + design->
diodesInRow(0) *0.5 - 0.5;
669 std::pair<Amg::Vector3D, Amg::Vector3D > ends = {
677 std::pair<Amg::Vector3D, Amg::Vector3D> ends(element->
endsOfStrip(localPosition));
#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.
This is an Identifier helper class for the SCT subdetector.
Handle class for recording to StoreGate.
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.
int strip() const
Get strip number. Equivalent to phiIndex().
bool isValid() const
Test if its in a valid state.
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)
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
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
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.