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
94 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
96 ATH_CHECK(acts_tracking_geometry !=
nullptr);
99 ATH_CHECK(detectorElementToGeometryIdMap.isValid());
101 ATLASUncalibSourceLinkSurfaceAccessor surfaceAccessor{ *acts_tracking_geometry, **detectorElementToGeometryIdMap };
103 spBuilderConfig->slSurfaceAccessor
104 .connect<&ATLASUncalibSourceLinkSurfaceAccessor::operator()>(&surfaceAccessor);
106 const std::shared_ptr<const Acts::TrackingGeometry> trkGeometry =
m_trackingGeometryTool->trackingGeometry();
107 spBuilderConfig->trackingGeometry = trkGeometry;
110 auto spConstructor = [
this, &clusterContainer, &elements](
const Acts::Vector3 &
pos,
111 std::optional<double> ,
112 const Acts::Vector2 &
cov,
113 std::optional<double> ,
114 const boost::container::static_vector<Acts::SourceLink, 2> &slinks)
116 std::vector<std::size_t> measIndices;
117 std::array<StripInformationHelper, 2> stripInfos;
119 for (
const auto& slink : slinks){
125 if (
it != clusterContainer.
end()){
126 const auto cluster_index =
it - clusterContainer.
begin();
127 const auto id = hit->identifierHash();
129 size_t stripIndex = 0;
130 auto ends = this->
getStripEnds(atlasSourceLink, element, stripIndex);
133 measIndices.push_back(cluster_index);
134 stripInfos[
idx++] = std::move(stripInfo);
137 const auto& [firstInfo, secondInfo] = stripInfos;
138 const auto topHalfStripLength = 0.5*firstInfo.stripDirection().norm();
139 Eigen::Matrix<double, 3, 1> topStripDirection = -firstInfo.stripDirection()/(2.*topHalfStripLength);
140 Eigen::Matrix<double, 3, 1> topStripCenter = 0.5*firstInfo.trajDirection();
142 const auto bottomHalfStripLength = 0.5*secondInfo.stripDirection().norm();
143 Eigen::Matrix<double, 3, 1> bottomStripDirection = -secondInfo.stripDirection()/(2.*bottomHalfStripLength);
144 Eigen::Matrix<double, 3, 1> stripCenterDistance = firstInfo.stripCenter() - secondInfo.stripCenter();
147 sp.idHashes = {firstInfo.idHash(), secondInfo.idHash()};
148 sp.globPos =
pos.cast<
float>();
151 sp.measurementIndexes = measIndices;
152 sp.topHalfStripLength = topHalfStripLength;
153 sp.bottomHalfStripLength = bottomHalfStripLength;
154 sp.topStripDirection = topStripDirection.cast<
float>();
155 sp.bottomStripDirection = bottomStripDirection.cast<
float>();
156 sp.stripCenterDistance = stripCenterDistance.cast<
float>();
157 sp.topStripCenter = topStripCenter.cast<
float>();
162 auto spBuilder = std::make_shared<Acts::SpacePointBuilder<StripSP>>(*spBuilderConfig, spConstructor);
164 const auto hashesProc = (hashesToProcess.size() > 0 ? hashesToProcess : stripAccessor.
allIdentifiers());
165 for (
auto &idHash : hashesProc)
172 const std::vector<IdentifierHash>& others = *
properties.neighbours(idHash);
174 if ( others.empty())
continue;
180 size_t neighbour = 0;
181 while (not
search and neighbour < others.size()){
188 std::array<std::vector<std::pair<const xAOD::StripCluster *, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourClusters{};
189 std::array<std::vector<std::pair<ATLASUncalibSourceLink, size_t>>,
static_cast<size_t>(
nNeighbours)> neighbourSourceLinks{};
190 std::array<const InDetDD::SiDetectorElement *, static_cast<size_t>(
nNeighbours)> neighbourElements{};
192 auto groupStart = clusterContainer.
begin();
194 neighbourElements[0] = thisElement;
196 for (
auto start = this_range.first;
start != this_range.second; ++
start){
198 neighbourClusters[0].push_back(std::make_pair(*
start, position));
199 if ((*start)->identifierHash() != thisElement->
identifyHash()) {
200 throw std::logic_error(
"Identifier mismatch.");
203 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
210 std::array<double, 14> overlapExtents{};
220 if (not processOverlaps)
232 for (
const auto &otherHash : others){
233 if (++
n == Nmax)
break;
240 neighbourElements[neigbourIndices[
n]] = otherElement;
242 for (
auto start = this_range.first;
start != this_range.second; ++
start){
244 neighbourClusters[neigbourIndices[
n]].push_back(std::make_pair(*
start, position));
245 if ((*start)->identifierHash() != otherElement->
identifyHash()) {
246 throw std::logic_error(
"Identifier mismatch.");
249 neighbourSourceLinks[neigbourIndices[
n]].emplace_back(std::make_pair(slink, position));
262 overlapExtents[6] = -hwidth;
265 overlapExtents[9] = hwidth;
271 overlapExtents[11] = hwidth;
272 overlapExtents[12] = -hwidth;
303 return StatusCode::SUCCESS;