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
103 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
108 ATLASUncalibSourceLinkSurfaceAccessor surfaceAccessor{ &(*m_ATLASConverterTool), &tracking_surface_helper };
110 spBuilderConfig->slSurfaceAccessor
111 .connect<&ATLASUncalibSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
113 const std::shared_ptr<const Acts::TrackingGeometry> trkGeometry =
m_trackingGeometryTool->trackingGeometry();
114 spBuilderConfig->trackingGeometry = trkGeometry;
117 auto spConstructor = [
this, &clusterContainer, &elements](
const Acts::Vector3 &
pos,
118 std::optional<double> ,
119 const Acts::Vector2 &
cov,
120 std::optional<double> ,
121 const boost::container::static_vector<Acts::SourceLink, 2> &slinks)
123 std::vector<std::size_t> measIndices;
124 std::array<StripInformationHelper, 2> stripInfos;
126 for (
const auto& slink : slinks){
132 if (
it != clusterContainer.
end()){
133 const auto cluster_index =
it - clusterContainer.
begin();
134 const auto id = hit->identifierHash();
136 size_t stripIndex = 0;
137 auto ends = this->
getStripEnds(atlasSourceLink, element, stripIndex);
140 measIndices.push_back(cluster_index);
141 stripInfos[
idx++] = std::move(stripInfo);
144 const auto& [firstInfo, secondInfo] = stripInfos;
145 const auto topHalfStripLength = 0.5*firstInfo.stripDirection().norm();
146 Eigen::Matrix<double, 3, 1> topStripDirection = -firstInfo.stripDirection()/(2.*topHalfStripLength);
147 Eigen::Matrix<double, 3, 1> topStripCenter = 0.5*firstInfo.trajDirection();
149 const auto bottomHalfStripLength = 0.5*secondInfo.stripDirection().norm();
150 Eigen::Matrix<double, 3, 1> bottomStripDirection = -secondInfo.stripDirection()/(2.*bottomHalfStripLength);
151 Eigen::Matrix<double, 3, 1> stripCenterDistance = firstInfo.stripCenter() - secondInfo.stripCenter();
154 sp.idHashes = {firstInfo.idHash(), secondInfo.idHash()};
155 sp.globPos =
pos.cast<
float>();
158 sp.measurementIndexes = measIndices;
159 sp.topHalfStripLength = topHalfStripLength;
160 sp.bottomHalfStripLength = bottomHalfStripLength;
161 sp.topStripDirection = topStripDirection.cast<
float>();
162 sp.bottomStripDirection = bottomStripDirection.cast<
float>();
163 sp.stripCenterDistance = stripCenterDistance.cast<
float>();
164 sp.topStripCenter = topStripCenter.cast<
float>();
169 auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
171 const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.
allIdentifiers());
172 for (
auto &idHash : hashesProc)
179 const std::vector<IdentifierHash>& others = *
properties.neighbours(idHash);
181 if ( others.empty())
continue;
187 size_t neighbour = 0;
188 while (not
search and neighbour < others.size()){
195 std::array<std::vector<std::pair<const xAOD::StripCluster *, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourClusters{};
196 std::array<std::vector<std::pair<ATLASUncalibSourceLink, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourSourceLinks{};
197 std::array<const InDetDD::SiDetectorElement *, static_cast<size_t>(
nNeighbours)> neighbourElements{};
199 auto groupStart = clusterContainer.
begin();
201 neighbourElements[0] = thisElement;
203 for (
auto start = this_range.first;
start != this_range.second; ++
start){
205 neighbourClusters[0].push_back(std::make_pair(*
start, position));
206 if ((*start)->identifierHash() != thisElement->
identifyHash()) {
207 throw std::logic_error(
"Identifier mismatch.");
210 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
217 std::array<double, 14> overlapExtents{};
227 if (not processOverlaps)
239 for (
const auto &otherHash : others){
240 if (++
n == Nmax)
break;
247 neighbourElements[neigbourIndices[
n]] = otherElement;
249 for (
auto start = this_range.first;
start != this_range.second; ++
start){
251 neighbourClusters[neigbourIndices[
n]].push_back(std::make_pair(*
start, position));
252 if ((*start)->identifierHash() != otherElement->
identifyHash()) {
253 throw std::logic_error(
"Identifier mismatch.");
256 neighbourSourceLinks[neigbourIndices[
n]].emplace_back(std::make_pair(slink, position));
269 overlapExtents[6] = -hwidth;
272 overlapExtents[9] = hwidth;
278 overlapExtents[11] = hwidth;
279 overlapExtents[12] = -hwidth;
309 spacePoints, overlapSpacePoints) );
312 return StatusCode::SUCCESS;