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 each element, the extremes of these ranges are saved in the overlapExtents array which is used later on
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
90 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
92 ATH_CHECK(acts_tracking_geometry !=
nullptr);
95 ATH_CHECK(detectorElementToGeometryIdMap.isValid());
97 ATLASUncalibSourceLinkSurfaceAccessor surfaceAccessor{ *acts_tracking_geometry, **detectorElementToGeometryIdMap };
99 spBuilderConfig->slSurfaceAccessor
100 .connect<&ATLASUncalibSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
102 const std::shared_ptr<const Acts::TrackingGeometry> trkGeometry =
m_trackingGeometryTool->trackingGeometry();
103 spBuilderConfig->trackingGeometry = trkGeometry;
106 auto spConstructor = [
this, &clusterContainer, &elements](
const Acts::Vector3 &
pos,
107 std::optional<double> ,
108 const Acts::Vector2 &
cov,
109 std::optional<double> ,
110 const boost::container::static_vector<Acts::SourceLink, 2> &slinks)
112 std::vector<std::size_t> measIndices;
113 std::array<StripInformationHelper, 2> stripInfos;
115 for (
const auto& slink : slinks){
121 if (
it != clusterContainer.
end()){
122 const auto cluster_index =
it - clusterContainer.
begin();
123 const auto id = hit->identifierHash();
125 size_t stripIndex = 0;
126 auto ends = this->
getStripEnds(atlasSourceLink, element, stripIndex);
129 measIndices.push_back(cluster_index);
130 stripInfos[
idx++] = std::move(stripInfo);
133 const auto& [firstInfo, secondInfo] = stripInfos;
134 const auto topHalfStripLength = 0.5*firstInfo.stripDirection().norm();
135 Eigen::Matrix<double, 3, 1> topStripDirection = -firstInfo.stripDirection()/(2.*topHalfStripLength);
136 Eigen::Matrix<double, 3, 1> topStripCenter = 0.5*firstInfo.trajDirection();
138 const auto bottomHalfStripLength = 0.5*secondInfo.stripDirection().norm();
139 Eigen::Matrix<double, 3, 1> bottomStripDirection = -secondInfo.stripDirection()/(2.*bottomHalfStripLength);
140 Eigen::Matrix<double, 3, 1> stripCenterDistance = firstInfo.stripCenter() - secondInfo.stripCenter();
143 sp.idHashes = {firstInfo.idHash(), secondInfo.idHash()};
144 sp.globPos =
pos.cast<
float>();
147 sp.measurementIndexes = measIndices;
148 sp.topHalfStripLength = topHalfStripLength;
149 sp.bottomHalfStripLength = bottomHalfStripLength;
150 sp.topStripDirection = topStripDirection.cast<
float>();
151 sp.bottomStripDirection = bottomStripDirection.cast<
float>();
152 sp.stripCenterDistance = stripCenterDistance.cast<
float>();
153 sp.topStripCenter = topStripCenter.cast<
float>();
158 auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
160 const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.
allIdentifiers());
161 for (
auto &idHash : hashesProc)
168 const std::vector<IdentifierHash>& others = *
properties.neighbours(idHash);
170 if ( others.empty())
continue;
176 size_t neighbour = 0;
177 while (not
search and neighbour < others.size()){
184 std::array<std::vector<std::pair<const xAOD::StripCluster *, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourClusters{};
185 std::array<std::vector<std::pair<ATLASUncalibSourceLink, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourSourceLinks{};
186 std::array<const InDetDD::SiDetectorElement *, static_cast<size_t>(
nNeighbours)> neighbourElements{};
188 auto groupStart = clusterContainer.
begin();
190 neighbourElements[0] = thisElement;
192 for (
auto start = this_range.first;
start != this_range.second; ++
start){
194 neighbourClusters[0].push_back(std::make_pair(*
start, position));
195 if ((*start)->identifierHash() != thisElement->
identifyHash()) {
196 throw std::logic_error(
"Identifier mismatch.");
199 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
206 std::array<double, 14> overlapExtents{};
216 if (not processOverlaps)
228 for (
const auto &otherHash : others){
229 if (++
n == Nmax)
break;
236 neighbourElements[neigbourIndices[
n]] = otherElement;
238 for (
auto start = this_range.first;
start != this_range.second; ++
start){
240 neighbourClusters[neigbourIndices[
n]].push_back(std::make_pair(*
start, position));
241 if ((*start)->identifierHash() != otherElement->
identifyHash()) {
242 throw std::logic_error(
"Identifier mismatch.");
245 neighbourSourceLinks[neigbourIndices[
n]].emplace_back(std::make_pair(slink, position));
258 overlapExtents[6] = -hwidth;
261 overlapExtents[9] = hwidth;
267 overlapExtents[11] = hwidth;
268 overlapExtents[12] = -hwidth;
298 spacePoints, overlapSpacePoints) );
301 return StatusCode::SUCCESS;