24 #include <unordered_set>
25 #include <nlohmann/json.hpp>
37 const auto*
re = prd->readoutElement();
38 switch(prd->channelType()) {
40 return re->stripDesign(prd->measurementHash());
42 return re->wireDesign(prd->measurementHash());
44 return re->padDesign(prd->measurementHash());
51 const auto& design = getDesign(sp);
54 return 0.5* design.stripLength(prd->channelNumber());
62 using namespace SegmentFitHelpers;
70 ATH_CHECK(m_visionTool.retrieve(DisableTool{m_visionTool.empty()}));
72 if (!(m_idHelperSvc->hasMM() || m_idHelperSvc->hasSTGC())) {
73 ATH_MSG_ERROR(
"MM or STGC not part of initialized detector layout");
74 return StatusCode::FAILURE;
77 return StatusCode::SUCCESS;
83 for (std::size_t
l = 0;
l < sortedSp.size(); ++
l) {
84 emptyKeeper[
l].resize(sortedSp[
l].
size(), 0);
93 const auto& design = getDesign(sp);
94 if (!design.hasStereoAngle()) {
97 return design.stereoAngle() > 0. ? StripOrient::U : StripOrient::V;
116 bool below{
true}, above{
true};
117 switch (classifyStrip(testHit)) {
121 const double halfLength = 0.5* stripHalfLength(testHit);
127 below = estPlaneArrivalDn.y() >
std::max(leftEdge.y(), rightEdge.y());
129 above = estPlaneArrivalUp.y() <
std::min(leftEdge.y(), rightEdge.y());
134 below = estPlaneArrivalDn.y() > hY;
136 above = estPlaneArrivalUp.y() < hY;
145 << (below || above ?
" is outside the window" :
" is inside the window"));
147 return HitWindow::tooLow;
150 return HitWindow::tooHigh;
156 #define TEST_HIT_CORRIDOR(LAYER, HIT_ITER, START_LAYER) \
158 const SpacePoint* testMe = combinatoricLayers[LAYER].get()[HIT_ITER]; \
159 if (usedHits[LAYER].get()[HIT_ITER]) { \
160 ATH_MSG_VERBOSE(__func__<<":"<<__LINE__<<" - " \
161 <<m_idHelperSvc->toString(testMe->identify()) \
162 <<" already used in good seed." ); \
165 const HitWindow inWindow = hitFromIPCorridor(*testMe, beamSpot, dirEstUp, dirEstDn); \
166 if(inWindow == HitWindow::tooHigh) { \
167 ATH_MSG_VERBOSE(__func__<<":"<<__LINE__<<" - Hit " \
168 <<m_idHelperSvc->toString(testMe->identify()) \
169 <<" is beyond the corridor. Break loop"); \
171 } else if (inWindow == HitWindow::tooLow) { \
172 START_LAYER = HIT_ITER + 1; \
173 ATH_MSG_VERBOSE(__func__<<":"<<__LINE__<<" - Hit " \
174 <<m_idHelperSvc->toString(testMe->identify()) \
175 <<" is still below the corridor. Update start to " \
186 seedHitsFromLayers.clear();
187 std::size_t maxSize{1};
188 for (
const HitVec& hitVec : combinatoricLayers) {
189 maxSize = maxSize * hitVec.size();
191 seedHitsFromLayers.reserve(maxSize);
194 unsigned int iterLay0{0}, iterLay1{0}, iterLay2{0}, iterLay3{0};
195 unsigned int startLay1{0}, startLay2{0}, startLay3{0};
197 for( ; iterLay0 < combinatoricLayers[0].get().
size() ; ++iterLay0){
199 if (usedHits[0].
get()[iterLay0]) {
202 const SpacePoint* hit0 = combinatoricLayers[0].get()[iterLay0];
213 for( iterLay1 = startLay1; iterLay1 < combinatoricLayers[1].get().
size() ; ++iterLay1){
215 for( iterLay2 = startLay2; iterLay2 < combinatoricLayers[2].get().
size() ; ++iterLay2){
217 for( iterLay3 = startLay3; iterLay3 < combinatoricLayers[3].get().
size(); ++iterLay3){
219 seedHitsFromLayers.emplace_back(
std::array{hit0, combinatoricLayers[1].get()[iterLay1],
220 combinatoricLayers[2].
get()[iterLay2],
221 combinatoricLayers[3].
get()[iterLay3]});
227 #undef TEST_HIT_CORRIDOR
239 for (std::size_t
i = 0;
i < extensionLayers.size(); ++
i) {
243 unsigned int indexOfHit =
layer.size() + 1;
244 unsigned int triedHit{0};
248 for (
unsigned int j = 0; j <
layer.size(); ++j) {
249 if (usedHits[
i].
get().at(j)) {
252 auto hit =
layer.at(j);
254 ATH_MSG_VERBOSE(
"Trying extension with hit " << m_idHelperSvc->toString(hit->identify()));
257 if (
pull > minPull) {
271 if (minPull < m_minPullThreshold) {
272 const auto* bestCand =
layer.at(indexOfHit);
273 ATH_MSG_VERBOSE(
"Extension successfull - hit" << m_idHelperSvc->toString(bestCand->identify())
275 <<
", dir: "<<
Amg::toString(bestCand->directionInChamber())<<
" found with pull "<<minPull);
276 combinatoricHits.push_back(bestCand);
279 return combinatoricHits;
282 std::unique_ptr<SegmentSeed>
289 HitVec hits{initialSeed.begin(), initialSeed.end()};
296 for (std::size_t
i = 0;
i < 4; ++
i) {
297 const double halfLength = stripHalfLength(*
hits[
i]);
299 if (std::abs(
params[
i]) > halfLength) {
300 ATH_MSG_VERBOSE(
"Seed Rejection: Invalid seed - outside of the strip's length");
307 double interceptX = segPos.x();
308 double interceptY = segPos.y();
312 auto extendedHits = extendHits(segPos, direction, extensionLayers, usedHits);
313 hits.insert(
hits.end(), extendedHits.begin(), extendedHits.end());
314 return std::make_unique<SegmentSeed>(tanTheta, interceptY, tanPhi,
315 interceptX,
hits.size(),
316 std::move(
hits),
max.parentBucket());
320 std::vector<std::unique_ptr<SegmentSeed>>
325 const HitLayVec& stripHitsLayers{hitLayers.stripHits()};
326 const std::size_t layerSize = stripHitsLayers.size();
328 std::vector<std::unique_ptr<SegmentSeed>> seeds{};
337 if (m_visionTool.isEnabled()) {
340 constexpr
double legX{0.2};
354 const double pull2 = (mmClust->localPosition<1>().
x() - simHit->
localPosition().x()) / std::sqrt(mmClust->localCovariance<1>().x());
359 m_visionTool->visualizeBucket(Gaudi::Hive::currentContext(), *
max.parentBucket(),
360 "truth", std::move(primitives));
365 std::array<const SpacePoint*, 4> seedHits{};
369 for (std::size_t
i = 0;
i < layerSize - 3; ++
i) {
370 seedHits[0] = stripHitsLayers[
i].front();
371 for (std::size_t j =
i + 1; j < layerSize - 2; ++j) {
372 seedHits[1] = stripHitsLayers[j].front();
373 for (std::size_t
k = j + 1;
k < layerSize - 1; ++
k) {
374 seedHits[2] = stripHitsLayers[
k].front();
375 for (std::size_t
l =
k + 1;
l < layerSize; ++
l) {
376 seedHits[3] = stripHitsLayers[
l].front();
377 AmgSymMatrix(2) bMatrix = CombinatorialSeedSolver::betaMatrix(seedHits);
378 if (std::abs(bMatrix.determinant()) < 1.e-6) {
382 const HitLaySpan_t layers{stripHitsLayers[
i], stripHitsLayers[j], stripHitsLayers[
k], stripHitsLayers[
l]};
383 UsedHitSpan_t usedHits{allUsedHits[
i], allUsedHits[j], allUsedHits[
k], allUsedHits[
l]};
385 constructPrelimnarySeeds(globToLocal.translation(),
layers, usedHits, preLimSeeds);
390 usedExtensionHits.reserve(stripHitsLayers.size());
391 extensionLayers.reserve(stripHitsLayers.size());
392 for (std::size_t
e = 0 ;
e < stripHitsLayers.size(); ++
e) {
393 if (!(
e ==
i ||
e == j ||
e ==
k ||
e ==
l)){
394 extensionLayers.emplace_back(stripHitsLayers[
e]);
395 usedExtensionHits.emplace_back(allUsedHits[
e]);
400 for (
auto &combinatoricHits : preLimSeeds) {
401 auto seed = buildSegmentSeed(combinatoricHits, bMatrix,
max, extensionLayers, usedExtensionHits);
403 markHitsAsUsed(*seed,stripHitsLayers, allUsedHits);
404 seeds.push_back(std::move(seed));
418 for (
const auto* sp : seed.getHitsInMax()) {
420 for (std::size_t lIdx = 0; !
found && lIdx < allSortHits.size(); ++lIdx) {
421 const HitVec& hVec{allSortHits[lIdx]};
422 for (std::size_t hIdx = 0 ; hIdx < hVec.size(); ++hIdx) {
423 if (hVec[hIdx] == sp) {
424 usedHitMarker[lIdx][hIdx] =
true;
442 ATH_CHECK(writeMaxima.record(std::make_unique<SegmentSeedContainer>()));
447 std::vector<std::unique_ptr<SegmentSeed>> seeds = findSeedsFromMaximum(*
max, *gctx);
449 for(
const auto& hitMax :
max->getHitsInMax()){
450 ATH_MSG_VERBOSE(
"Hit "<<m_idHelperSvc->toString(hitMax->identify())<<
", "
455 for (
auto &seed : seeds) {
457 std::stringstream sstr{};
458 sstr<<
"Seed tanTheta = "<<seed->tanTheta()<<
", y0 = "<<seed->interceptY()
459 <<
", tanPhi = "<<seed->tanPhi()<<
", x0 = "<<seed->interceptX()<<
", hits in the seed "
460 <<seed->getHitsInMax().size()<<std::endl;
462 for(
const auto& hit : seed->getHitsInMax()){
463 sstr<<
" *** Hit "<<m_idHelperSvc->toString(hit->identify())<<
", "
468 if (m_visionTool.isEnabled()) {
469 m_visionTool->visualizeSeed(ctx, *seed,
"#phi-combinatorialSeed");
471 writeMaxima->push_back(std::move(seed));
474 return StatusCode::SUCCESS;