22 #include <unordered_set>
23 #include <nlohmann/json.hpp>
42 ATH_MSG_ERROR(
"MM or STGC not part of initialized detector layout");
43 return StatusCode::FAILURE;
46 return StatusCode::SUCCESS;
57 Amg::intersect<3>(startPos, dirEstUp, testHit->
planeNormal(), planeOffSet).value_or(0) * dirEstUp;
59 Amg::intersect<3>(startPos, dirEstDn, testHit->
planeNormal(), planeOffSet).value_or(0) * dirEstDn;
61 switch (testHit->
type()) {
65 const double halfLength = prd->
readoutElement()->
stripLayer(prd->measurementHash()).design().stripLength(prd->channelNumber()) * 0.5;
70 const bool below = estPlaneArrivalDn.y() >
std::max(leftEdge.y(), rightEdge.y());
71 const bool above = estPlaneArrivalUp.y() <
std::min(leftEdge.y(), rightEdge.y());
73 << (below || above ?
" is outside the window" :
" is inside the window"));
90 const HitLayVec &combinatoricLayers)
const {
95 unsigned int iterLay0{0}, iterLay1{0}, iterLay2{0}, iterLay3{0};
96 unsigned int startLay1{0}, startLay2{0}, startLay3{0};
98 for( ; iterLay0 < combinatoricLayers[0].size() ; ++iterLay0){
100 const SpacePoint* hit0 = combinatoricLayers[0][iterLay0];
111 for( iterLay1 = startLay1; iterLay1 < combinatoricLayers[1].size() ; ++iterLay1){
112 const SpacePoint* hit1 = combinatoricLayers[1][iterLay1];
121 for( iterLay2 = startLay2; iterLay2 < combinatoricLayers[2].size() ; ++iterLay2){
122 const SpacePoint* hit2 = combinatoricLayers[2][iterLay2];
125 iterLay1 = combinatoricLayers[1].size();
131 for( iterLay3 = startLay3; iterLay3 < combinatoricLayers[3].size(); ++iterLay3){
132 const SpacePoint* hit3 = combinatoricLayers[3][iterLay3];
135 iterLay1 = combinatoricLayers[1].size();
136 iterLay2 = combinatoricLayers[2].size();
142 seedHitsFromLayers.emplace_back(
HitVec{hit0, hit1, hit2, hit3});
147 return seedHitsFromLayers;
153 const HitLayVec& stripHitsLayers)
const {
159 for (
unsigned int i = 0;
i < stripHitsLayers.size();
i++) {
161 double offset = stripHitsLayers[
i].front()->positionInChamber().dot(stripHitsLayers[
i].front()->planeNormal());
162 const Amg::Vector3D extrapPos = startPos + Amg::intersect<3>(startPos, direction, stripHitsLayers[
i].front()->planeNormal(),
offset).value_or(0) * direction;
164 unsigned int indexOfHit = stripHitsLayers[
i].size()+1;
165 unsigned int triedHit{0};
169 for (
unsigned int j = 0; j < stripHitsLayers[
i].size(); j++) {
170 auto hit = stripHitsLayers[
i].at(j);
175 if (
pull > minPull) {
192 <<
Amg::toString(stripHitsLayers[
i].at(indexOfHit)->positionInChamber())<<
", dir: "<<
Amg::toString(stripHitsLayers[
i].at(indexOfHit)->directionInChamber())<<
" found with pull "<<minPull);
193 combinatoricHits.push_back(stripHitsLayers[
i].at(indexOfHit));
196 return combinatoricHits;
199 std::unique_ptr<SegmentSeed>
203 const HitLayVec& extensionLayers)
const {
206 ATH_MSG_VERBOSE(
"Seed Rejection: Wrong number of initial layers for seeding --they should be four");
217 double interceptX = segPos.x();
218 double interceptY = segPos.y();
221 for (std::size_t
i = 0;
i < 4;
i++) {
227 double halfLength = 0.5 * clust->
readoutElement()->
stripLayer(clust->measurementHash()).design().stripLength(clust->channelNumber());
229 if (std::abs(
params[
i]) > halfLength) {
230 ATH_MSG_VERBOSE(
"Seed Rejection: Invalid seed - outside of the strip's length");
237 auto extendedHits =
extendHits(segPos, direction, extensionLayers);
238 hits.insert(
hits.end(), extendedHits.begin(), extendedHits.end());
239 return std::make_unique<SegmentSeed>(tanTheta, interceptY, tanPhi,
240 interceptX,
hits.size(),
241 std::move(
hits),
max.parentBucket());
244 std::vector<std::unique_ptr<SegmentSeed>>
249 HitLayVec stripHitsLayers{hitLayers.stripHits()};
251 std::vector<std::unique_ptr<SegmentSeed>> seeds;
253 unsigned int layerSize = stripHitsLayers.size();
263 constexpr
double legX{0.2};
266 const auto* mmClust =
static_cast<const xAOD::MMCluster*
>(sp->primaryMeasurement());
277 const double pull2 = (mmClust->localPosition<1>().
x() - simHit->
localPosition().x()) / std::sqrt(mmClust->localCovariance<1>().x());
282 m_visionTool->visualizeBucket(Gaudi::Hive::currentContext(), *
max.parentBucket(),
283 "truth", std::move(primitives));
287 std::array<const SpacePoint*, 4> seedHits{};
288 for (std::size_t
i = 0;
i < layerSize - 3; ++
i) {
289 seedHits[0] = stripHitsLayers[
i].front();
290 for (std::size_t j =
i + 1; j < layerSize - 2; ++j) {
291 seedHits[1] = stripHitsLayers[j].front();
292 for (std::size_t
k = j + 1;
k < layerSize - 1; ++
k) {
293 seedHits[2] = stripHitsLayers[
k].front();
294 for (std::size_t
l =
k + 1;
l < layerSize; ++
l) {
295 seedHits[3] = stripHitsLayers[
l].front();
296 AmgSymMatrix(2) bMatrix = CombinatorialSeedSolver::betaMatrix(seedHits);
297 if (std::abs(bMatrix.determinant()) < 1.e-6) {
302 const HitLayVec layers{stripHitsLayers[
i], stripHitsLayers[j], stripHitsLayers[
k], stripHitsLayers[
l]};
310 std::copy_if(stripHitsLayers.begin(), stripHitsLayers.end(), std::back_inserter(extensionLayers),
312 const Identifier gasGapId = m_idHelperSvc->gasGapId(stripLayer.front()->identify());
313 return std::ranges::find_if(layers,[&gasGapId, this](const HitVec& spacePoints){
314 return gasGapId == m_idHelperSvc->gasGapId(spacePoints.front()->identify());
320 for (
auto &combinatoricHits :
result) {
323 seeds.push_back(std::move(seed));
346 ATH_CHECK(writeMaxima.record(std::make_unique<SegmentSeedContainer>()));
351 std::vector<std::unique_ptr<SegmentSeed>> seeds = findSeedsFromMaximum(*
max, *gctx);
353 for(
const auto& hitMax :
max->getHitsInMax()){
354 ATH_MSG_VERBOSE(
"Hit "<<m_idHelperSvc->toString(hitMax->identify())<<
", "
358 for (
auto &seed : seeds) {
359 ATH_MSG_VERBOSE(
"Seed tanTheta = "<<seed->tanTheta()<<
", y0 = "<<seed->interceptY()
360 <<
", tanPhi = "<<seed->tanPhi()<<
", x0 = "<<seed->interceptX()<<
", hits in the seed "<<seed->getHitsInMax().size());
362 for(
const auto& hit : seed->getHitsInMax()){
366 if (m_visionTool.isEnabled()) {
367 m_visionTool->visualizeSeed(ctx, *seed,
"#phi-combinatorialSeed");
369 writeMaxima->push_back(std::move(seed));
374 return StatusCode::SUCCESS;