11 #include <Acts/Utilities/Enumerate.hpp>
13 #include <Acts/Utilities/Enumerate.hpp>
18 using namespace SegmentFit;
19 using namespace SegmentFitHelpers;
23 return std::visit([](
const auto&
cov) ->
double{
28 return cutRange[0] <=
value &&
value <= cutRange[1];
32 ostr<<
"two circle solution with ";
34 ostr<<
"y0: "<<Y0<<
" pm "<<dY0;
43 const Config& configuration):
46 m_segmentSeed{segmentSeed} {
48 if (m_hitLayers.mdtHits().empty())
return;
50 if (std::ranges::find_if(m_hitLayers.mdtHits(), [
this](
const HitVec&
vec){
51 return vec.size() > m_cfg.busyLayerLimit;
52 }) != m_hitLayers.mdtHits().end()) {
53 m_cfg.startWithPattern =
false;
56 m_upperLayer = m_hitLayers.mdtHits().size()-1;
59 while (m_lowerLayer < m_upperLayer && m_hitLayers.mdtHits()[m_lowerLayer].size() >m_cfg.busyLayerLimit){
63 while (m_lowerLayer < m_upperLayer && m_hitLayers.mdtHits()[m_upperLayer].size() > m_cfg.busyLayerLimit) {
68 std::stringstream sstr{};
69 for (
const auto& [layCount,
layer] : Acts::enumerate(m_hitLayers.mdtHits())) {
70 sstr<<
"Mdt-hits in layer "<<layCount<<
": "<<
layer.size()<<std::endl;
72 sstr<<
" **** "<<hit->msSector()->idHelperSvc()->toString(hit->identify())<<
" "
73 <<
Amg::toString(hit->positionInChamber())<<
", driftRadius: "<<hit->driftRadius()<<std::endl;
76 for (
const auto& [layCount,
layer] : Acts::enumerate(m_hitLayers.stripHits())) {
77 sstr<<
"Hits in layer "<<layCount<<
": "<<
layer.size()<<std::endl;
79 sstr<<
" **** "<<hit->msSector()->idHelperSvc()->toString(hit->identify())<<
" "
80 <<
Amg::toString(hit->positionInChamber())<<
", driftRadius: "<<hit->driftRadius()<<std::endl;
83 ATH_MSG_VERBOSE(
"SeedGenerator - sorting of hits done. Mdt layers: "<<m_hitLayers.mdtHits().size()
84 <<
", strip layers: "<<m_hitLayers.stripHits().size()<<std::endl<<sstr.str());
116 std::optional<MdtSegmentSeedGenerator::DriftCircleSeed>
118 std::optional<DriftCircleSeed>
found = std::nullopt;
121 found = std::make_optional<DriftCircleSeed>();
156 std::optional<MdtSegmentSeedGenerator::DriftCircleSeed>
168 const int signTop = signs[0];
169 const int signBot = signs[1];
175 const double thetaTubes = std::atan2(D.y(), D.z());
176 const double distTubes = std::hypot(D.y(), D.z());
178 <<
", driftRadius: "<<bottomHit->
driftRadius()<<
" - top tube "<<idHelperSvc->toString(topHit->
identify())
185 double theta{thetaTubes - std::asin(std::clamp(R / distTubes, -1., 1.))};
187 double Y0 = bottomPos.y()*seedDir.z() - bottomPos.z()*seedDir.y() + signBot*bottomHit->
driftRadius();
188 double combDriftUncert{std::sqrt(bottomPrd->driftRadiusCov() + topPrd->driftRadiusCov())};
194 const auto [linePos, lineDir] =
makeLine(candidateSeed.parameters);
199 R = signBot * calibBottom->driftRadius() - signTop * calibTop->driftRadius();
201 theta = thetaTubes - std::asin(std::clamp(R / distTubes, -1., 1.));
203 Y0 = bottomPos.y()*seedDir.z() - bottomPos.z()*seedDir.y() + signBot*bottomHit->
driftRadius();
215 const Amg::Vector3D seedPos = Y0 / seedDir.z() * Amg::Vector3D::UnitY();
217 assert(std::abs(topPos.y()*seedDir.z() - topPos.z() * seedDir.y() + signTop*topHit->
driftRadius() - Y0) < std::numeric_limits<float>::epsilon() );
218 ATH_MSG_VERBOSE(
"Candidate seed theta: "<<theta<<
", tanTheta: "<<(seedDir.y() / seedDir.z())<<
", y0: "<<Y0/seedDir.z());
222 solCandidate.theta = theta;
224 solCandidate.dTheta = combDriftUncert / std::sqrt(1. -
std::pow(std::clamp(R / distTubes, -1., 1.), 2)) / distTubes;
225 solCandidate.dY0 = std::hypot(-bottomPos.y()*seedDir.y() + bottomPos.z()*seedDir.z(), 1.) * solCandidate.dTheta;
229 unsigned int nMdt{0};
242 solCandidate.seedHits.emplace_back(calibHit->spacePoint());
243 candidateSeed.measurements.push_back(std::move(calibHit));
254 solCandidate.solutionSigns =
driftSigns(seedPos, seedDir, solCandidate.seedHits,
msg());
260 unsigned int nOverlap{0};
262 ATH_MSG_VERBOSE(
"Test seed against accepted "<<accepted<<
", updated signs: "<<corridor);
264 for (
unsigned int l = 0;
l < accepted.
seedHits.size(); ++
l){
269 if (nOverlap == corridor.size() && accepted.
seedHits.size() >= solCandidate.seedHits.size()) {
270 ATH_MSG_VERBOSE(
"Same set of hits collected within the same corridor");
276 return std::abs(seen.
Y0 - solCandidate.Y0) < std::hypot(seen.
dY0, solCandidate.dY0) &&
277 std::abs(seen.
theta - solCandidate.theta) < std::hypot(seen.
dTheta, solCandidate.dTheta);
295 ATH_MSG_VERBOSE(
"In event "<<ctx.eventID().event_number()<<
" found new seed solution "<<
toString(candidateSeed.parameters));
309 const auto [seedPos, seedDir] =
makeLine(candidateSeed.parameters);
315 / testMe->dimension();
319 if (
pull <= bestPull) {
330 return candidateSeed;
340 double norm{0.}, fitY0{0.};
343 std::vector<double> invCovs{};
346 for (
const std::unique_ptr<CalibratedSpacePoint>& hit : inSeed.
measurements) {
347 const double invCov = 1./
driftCov(*hit);
350 centerOfGravity+= invCov *
pos;
351 invCovs.push_back(invCov);
352 const int sign =
y0 -
pos.y() * seedDir.z() +
pos.z()* seedDir.y() > 0 ? 1 : -1;
353 fitY0 += invCov *
sign * hit->driftRadius();
357 const double invNorm = 1./
norm;
359 centerOfGravity *= invNorm;
361 double Tzzyy{0.}, Tyz{0.}, Trz{0.}, Try{0.};
362 for (
const auto&[covIdx, hit] : Acts::enumerate(inSeed.
measurements)) {
363 const double invCov = invCovs[covIdx]*invNorm;
367 Tyz += invCov *
pos.y()*
pos.z();
368 Trz += invCov *
sign*
pos.z() * hit->driftRadius();
369 Try += invCov *
sign*
pos.y() * hit->driftRadius();
372 const double thetaMin = - (Tzzyy - Try) / (4* Tyz + Trz);
373 const double thetaDet =
std::pow(Tzzyy -Try,2) + 4*(Tyz + Trz)*(2*Tyz + 0.5*Trz);
374 const double thetaGuess = thetaMin + (theta > thetaMin ? 1. : -1.)*std::sqrt(thetaDet) / (4*Tyz + Trz);
377 ATH_MSG_VERBOSE(
"Start fast fit seed: "<<theta<<
", guess: "<<thetaGuess
378 <<
", y0: "<<
y0<<
", fitY0: "<<fitY0<<
", centre: "<<
Amg::toString(centerOfGravity));
381 bool converged{
false};
384 const double thetaPrime = 0.5*Tzzyy *twoTheta.sn - Tyz * twoTheta.cs - Trz * seedDir.z() - Try * seedDir.y();
390 const double thetaTwoPrime = Tzzyy * twoTheta.cs + 2* Tyz * twoTheta.sn + Trz * seedDir.y() - Try * seedDir.z();
391 const double update = thetaPrime / thetaTwoPrime;
392 ATH_MSG_VERBOSE(
"Fit iteration #"<<inSeed.
nIter<<
" -- theta: "<<theta<<
", thetaPrime: "<<thetaPrime
394 <<
" --> next theta "<<(theta - thetaPrime / thetaTwoPrime));
402 seedDir.y() = thetaUpdate.sn;
403 seedDir.z() = thetaUpdate.cs;