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
46 {
51
85
88
89 auto spBuilderConfig = std::make_shared<Acts::SpacePointBuilderConfig>();
90
92 spBuilderConfig->slSurfaceAccessor.connect<&detail::xAODUncalibMeasSurfAcc::operator()>(&surfaceAccessor);
94
95
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)
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;
105 for (const auto& slink : slinks){
107
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);
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
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>();
144
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) {
154 continue;
155 }
156
157 const std::vector<IdentifierHash>& others = *
properties.neighbours(idHash);
158
159 if (others.empty()) {
160 continue;
161 }
162
163
164
166 size_t neighbour = 0;
167 while (not
search and neighbour < others.size()){
169 neighbour++;
170 }
172 continue;
173 }
174
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
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.");
188 }
190 neighbourSourceLinks[0].emplace_back(std::make_pair(slink, position));
191 }
192 }
193
194 Identifier thisId = thisElement->
identify();
195
196
197 std::array<double, 14> overlapExtents{};
198
199 int Nmax = 4;
200
201
203 Nmax = 6;
204
205
206
207 if (not processOverlaps)
208 Nmax = 2;
209
212
213
214
215
216
218
219 for (const auto &otherHash : others){
220 if (++n == Nmax) break;
221
223 continue;
224
225 const InDetDD::SiDetectorElement *otherElement = elements.
getDetectorElement(otherHash);
226
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.");
234 }
236 neighbourSourceLinks[neigbourIndices[
n]].emplace_back(std::make_pair(slink, position));
237 }
238 }
239
240 switch (n){
242 {
245 break;
246 }
248 {
249 overlapExtents[6] = -hwidth;
252 overlapExtents[9] = hwidth;
253 break;
254 }
256 {
258 overlapExtents[11] = hwidth;
259 overlapExtents[12] = -hwidth;
261 break;
262 }
264 {
270 }
271 break;
272 }
273 default:
274 {
280 }
281 break;
282 }
283 }
284 }
285
287 spacePoints, overlapSpacePoints) );
288 }
289
290 return StatusCode::SUCCESS;
291 }
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
ATLASUncalibSourceLink makeATLASUncalibSourceLink(const xAOD::UncalibratedMeasurementContainer *container, std::size_t index, const EventContext &ctx)