15 #include "GaudiKernel/SystemOfUnits.h"
18 double rotatePhi(
double phi,
double rotationFraction) {
22 return phi + rotationFraction *
M_PI;
40 m_maximum_xydistance(3500),
41 m_maximum_rzdistance(1500),
43 m_splitpatterns(true),
45 m_bestphimatch(false),
46 m_flipdirectionforcosmics(false) {
47 declareInterface<IMuonCombinePatternTool>(
this);
66 return StatusCode::SUCCESS;
87 <<
" eta patterns: " << etaPatternCollection.
size()
88 <<
" phi patterns: " << phiPatternCollection.
size()
89 <<std::endl<<
"#################################################################################"
90 <<std::endl<<
"Print eta pattern collection "<<std::endl<<
m_printer->print(etaPatternCollection)
91 <<std::endl<<
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
92 <<std::endl<<
"Print phi pattern collection "<<std::endl<<
m_printer->print(phiPatternCollection)
95 for (
unsigned int etalevel = 0; etalevel < etaPatternCollection.
size(); etalevel++) {
97 if (etapattern->numberOfContainedPrds() == 0)
continue;
98 const Amg::Vector3D etaPatDir = etapattern->globalDirection().unit();
99 const Amg::Vector3D& etaPatPos = etapattern->globalPosition();
100 double theta = etaPatDir.theta();
101 const double phieta = etaPatDir.phi();
104 double z0 = etaPatPos.z();
105 double rz0 =
z0 * sctheta.
sn;
107 double eta_x = etaPatPos.x();
108 double eta_y = etaPatPos.y();
109 double pattern_z0 =
z0 + etaPatPos.perp() * sctheta.
cs / sctheta.
sn;
113 const double charge = eta_r0>= 0. ? 1. : -1;
115 const double curvature = etapattern->globalDirection().mag();
116 const double invcurvature = curvature > 2 ?
charge / curvature : 0.;
118 ATH_MSG_DEBUG(
" eta pattern info level: " << etalevel <<
" phi " << phieta <<
" theta " <<
theta <<
" x0 " << eta_x <<
" y0 "
119 << eta_y <<
" z0 " <<
z0 <<
" hits " << etapattern->numberOfContainedPrds());
123 int max_philevel = -1;
125 double dotprodbest = -1.;
127 bool ismatched =
false;
128 for (
unsigned int philevel = 0; philevel < phiPatternCollection.
size(); philevel++) {
129 CandPrdPatPtr phipattern{phiPatternCollection.
at(philevel), Unowned()};
130 if (phipattern->numberOfContainedPrds() == 0)
continue;
131 bool useTightAssociation =
false;
136 ATH_MSG_DEBUG(
" using tight cuts due to phi hits " << phipattern->numberOfContainedPrds() <<
" cut "
139 ATH_MSG_DEBUG(
" using tight cuts due to eta hits " << etapattern->numberOfContainedPrds() <<
" cut "
141 useTightAssociation =
true;
144 const Amg::Vector3D phiPatDir = phipattern->globalDirection().unit();
145 const double dotprod = phiPatDir.dot(etaPatDir);
147 if (dotprod > dotprodbest) {
148 dotprodbest = dotprod;
153 ATH_MSG_DEBUG(
" eta nr " << etalevel <<
" phi nr " << philevel <<
" inproduct " << dotprod <<
" sin angle "
157 double r0{0.}, phipattern_x{0.}, phipattern_y{0.},
phi{phiPatDir.phi()};
168 phipattern_x =
r0 * scphi.sn;
169 phipattern_y =
r0 * scphi.cs;
171 const Amg::Vector3D posphipattern = phipattern->globalPosition();
172 phipattern_x = posphipattern.x();
173 phipattern_y = posphipattern.y();
188 std::map<Identifier, ChamberInfo> infoPerChamber;
189 std::map<Muon::MuonStationIndex::StIndex, ChamberInfo> infoPerStation;
191 double average_distance{0};
192 int nhits_in_average{0}, nhits_inside_distance_cut{0};
194 double phiPatMin{1e9}, phiPatMax{-1e9};
196 for (
unsigned int phihitid = 0; phihitid < phipattern->numberOfContainedPrds(); phihitid++) {
199 double radius_hit = globalposhit.perp();
200 double dotprodradius = sctheta.
apply(radius_hit, globalposhit.z());
206 const double perp = scphi.apply(globalposhit.y(), globalposhit.x());
212 double distancetoline = std::abs(residu_distance_mm);
218 nhits_inside_distance_cut++;
220 average_distance += distancetoline;
222 if (!useTightAssociation) {
continue; }
226 double hitphi = globalposhit.phi();
235 phiPatMin =
std::min(hitphi,phiPatMin);
236 phiPatMax =
std::max(hitphi,phiPatMax);
240 if (nhits_in_average > 0) average_distance /= nhits_in_average;
242 ATH_MSG_DEBUG(
" Result for phi pattern: accepted hits " << nhits_inside_distance_cut <<
" average distance "
243 << average_distance);
245 bool etapattern_passed =
false;
246 for (
unsigned int etahitid = 0; etahitid < etapattern->numberOfContainedPrds(); etahitid++) {
249 const double etahitx = etaglobalposhit.x();
250 const double etahity = etaglobalposhit.y();
253 double etadotprod = scphi.apply(etahity, etahitx);
255 if (etadotprod < 0)
continue;
258 const double xdiff = phipattern_x - etahitx;
259 const double ydiff = phipattern_y - etahity;
260 const double etahitr = std::hypot(xdiff, ydiff);
262 bool hit_passed =
false;
270 const double scale = etahitr / 7000.;
272 }
else if (2 * etadistancetoline < etahitr) {
277 if (!hit_passed) {
continue; }
279 etapattern_passed =
true;
283 if (!useTightAssociation) { continue ;}
294 if (!mdtDetEl)
continue;
303 double phiLeft = gposLeft.phi();
307 double phiRight = gposRight.phi();
308 double phiMin =
std::min(phiRight, phiLeft);
309 double phiMax =
std::max(phiLeft ,phiRight);
314 double tubeL = (HVPos - ROPos).
mag();
315 double phiRO = ROPos.phi();
316 double phiHV = HVPos.phi();
317 double phiMinPos =
std::min(phiHV, phiRO);
318 double phiMaxPos =
std::max(phiRO, phiHV);
320 if (std::abs(phiMin - phiMinPos) > 0.01 || std::abs(phiMax - phiMaxPos) > 0.01) {
321 ATH_MSG_DEBUG(
" inconsistent Phi!!: from locToGlob (" << phiMin <<
"," << phiMax <<
"), from positions ("
322 << phiMinPos <<
"," << phiMaxPos <<
")");
324 double rotationFraction = 0.;
325 if (phiMin < 0 && phiMax > 0) {
326 if (phiMin < -0.75 * M_PI || phiMax > 0.75 *
M_PI)
327 rotationFraction = 1.5;
329 rotationFraction = 0.5;
330 }
else if (phiMax < 0) {
331 rotationFraction = 1.;
333 double phiMinR = rotatePhi(phiMin, rotationFraction);
334 double phiMaxR = rotatePhi(phiMax, rotationFraction);
335 phiMin =
std::min(phiMinR, phiMaxR);
336 phiMax =
std::max(phiMinR, phiMaxR);
338 phiMinR = rotatePhi(phiMinPos, rotationFraction);
339 phiMaxR = rotatePhi(phiMaxPos, rotationFraction);
340 phiMinPos =
std::min(phiMinR, phiMaxR);
341 phiMaxPos =
std::max(phiMinR, phiMaxR);
344 phiMin = phiMin > 0 ? phiMin - 0.1 : phiMin + 0.1;
345 phiMax = phiMax > 0 ? phiMax + 0.1 : phiMax - 0.1;
347 double phiMinSec{1.e9},phiMaxSec{-1.e9};
348 if (stInfo.
nphi > 0 && stInfo.
phiMin < 1000) {
349 phiMinR = rotatePhi(stInfo.
phiMin, rotationFraction);
350 phiMaxR = rotatePhi(stInfo.
phiMax, rotationFraction);
351 phiMinSec =
std::min(phiMinR, phiMaxR);
352 phiMaxSec =
std::max(phiMinR, phiMaxR);
357 if (phiMinSec > 0 && phiMaxSec > 0) {
358 if (phiMin > phiMaxSec || phiMax < phiMinSec)
inside =
false;
359 }
else if (phiMinSec < 0 && phiMaxSec < 0) {
364 if (phiMax < phiMaxSec)
inside =
false;
378 phiMinR = rotatePhi(phiPatMin, rotationFraction);
379 phiMaxR = rotatePhi(phiPatMax, rotationFraction);
380 double phiMinPat =
std::min(phiMinR, phiMaxR);
381 double phiMaxPat =
std::max(phiMinR, phiMaxR);
383 bool insidePat =
true;
385 if (phiMinPat > 0 && phiMaxPat > 0) {
386 if (phiMin > phiMaxPat || phiMax < phiMinPat) insidePat =
false;
387 }
else if (phiMinPat < 0 && phiMaxPat < 0) {
392 if (phiMax < phiMaxPat) insidePat =
false;
407 << std::setprecision(3) << std::setw(4) << phiMin <<
"," << std::setw(4) << phiMax <<
") "
408 <<
" from pos (" << std::setprecision(3) << std::setw(4) << phiMinPos <<
"," << std::setw(4)
409 << phiMaxPos <<
") ");
410 if (stInfo.
nphi > 0 && stInfo.
phiMin < 1000) {
411 ATH_MSG_DEBUG(
" phi range (" << std::setprecision(3) << std::setw(4) << stInfo.
phiMin <<
","
412 << std::setw(4) << stInfo.
phiMax <<
") ");
414 ATH_MSG_DEBUG(
" pat range (" << std::setprecision(3) << std::setw(4) << phiMinPat <<
"," << std::setw(4)
422 if (!etapattern_passed)
continue;
423 unsigned int netaPhiPairs = 0;
424 if (useTightAssociation) {
427 for (
auto& [chamberId, chamberInfo] : infoPerChamber) {
430 << chamberInfo.neta <<
" phi hits " << chamberInfo.nphi <<
" ninside "
431 << chamberInfo.ninside <<
" noutside " << chamberInfo.noutside <<
" ninside "
432 << chamberInfo.ninsidePat <<
" noutside " << chamberInfo.noutsidePat);
434 netaPhiPairs += (chamberInfo.neta && chamberInfo.nphi);
437 ATH_MSG_DEBUG(
" eta/phi pattern hit overlap " << netaPhiPairs);
438 if (!etapattern_passed) {
ATH_MSG_DEBUG(
" failed eta hit match "); }
439 if (nhits_inside_distance_cut < (phipattern->numberOfContainedPrds() * 0.25)) {
442 if (netaPhiPairs == 0) {
ATH_MSG_DEBUG(
" Bad match, no overlap "); }
445 ATH_MSG_VERBOSE(
" Eta pattern compatible with phi pattern, eta/phi overlap " << netaPhiPairs <<
" ass phi hits "
446 << nhits_inside_distance_cut <<
" tot phi hits "
447 << phipattern->numberOfContainedPrds()
448 <<(useTightAssociation ?
" using tight association ":
"" ));
451 if ((!useTightAssociation || netaPhiPairs > 0) && nhits_inside_distance_cut >= (phipattern->numberOfContainedPrds() * 0.25)) {
458 std::array<double,4> new_pars{
r0,
phi, pattern_z0,
theta};
460 phipattern = std::move(updatedpatterns.first);
461 etapattern = std::move(updatedpatterns.second);
462 ATH_MSG_DEBUG(
" Combination accepted with cosmic selection ");
463 }
else if (useTightAssociation) {
467 std::unique_ptr<Muon::MuonPrdPattern> etaPat = std::make_unique<Muon::MuonPrdPattern>(etapattern->globalPosition(), etapattern->globalDirection());
468 std::unique_ptr<Muon::MuonPrdPattern> phiPat = std::make_unique<Muon::MuonPrdPattern>(phipattern->globalPosition(), phipattern->globalDirection());
469 for (
unsigned int etahitid = 0; etahitid < etapattern->numberOfContainedPrds(); ++etahitid) {
474 if (chPos == infoPerChamber.end())
continue;
477 if (chPos->second.ninside == 0 && chPos->second.noutside > 0)
continue;
478 if (chPos->second.ninsidePat == 0 && chPos->second.noutsidePat > 0)
continue;
480 if (chPos->second.nphi == 0)
continue;
484 for (
unsigned int phihitid = 0; phihitid < phipattern->numberOfContainedPrds(); ++phihitid) {
489 if (chPos == infoPerChamber.end())
continue;
491 if (chPos->second.neta == 0)
continue;
494 phipattern = std::move(phiPat);
495 etapattern = std::move(etaPat);
500 ATH_MSG_DEBUG(
"Candidate FOUND eta " << etalevel <<
" phi " << philevel <<
" dotprod: " << dotprod);
502 if (average_distance < min_average_distance) {
504 min_average_distance = average_distance;
505 max_phipattern = phipattern;
506 max_philevel = philevel;
508 ATH_MSG_DEBUG(
" theta pattern " << etapattern->globalDirection().theta() <<
" phi "
509 << phipattern->globalDirection().phi() <<
"average distance " << average_distance
510 <<
" number of hits " << nhits_inside_distance_cut <<
" etalevel: " << etalevel);
514 }
else if (useTightAssociation && netaPhiPairs == 0 &&
515 nhits_inside_distance_cut >= (phipattern->numberOfContainedPrds() * 0.25)) {
516 ATH_MSG_DEBUG(
" Combination rejected by phi/eta overlap: average distance " << average_distance);
518 if (average_distance < min_average_distance) {
520 min_average_distance = average_distance;
521 max_phipattern = phipattern;
522 max_philevel = philevel;
530 ATH_MSG_DEBUG(
"Candidate FOUND eta " << etalevel <<
" phi " << max_philevel);
537 std::unique_ptr<Muon::MuonPrdPattern> assphipattern =
makeAssPhiPattern(*etapattern, phiEtaHitAssMap,
true);
538 ATH_MSG_DEBUG(
"No match found, trying to create associated phi pattern ");
543 bool subsetcheck =
false;
548 if ((*rit).first != etapattern) {
break; }
550 if (
subset(assphipattern.get(), (*rit).second.get())) {
561 ATH_MSG_DEBUG(
"Candidate FOUND eta " << etalevel <<
" and associated phipattern ");
571 assphipattern = std::move(updatedpatterns.first);
572 etapattern = std::move(updatedpatterns.second);
574 ATH_MSG_DEBUG(
" adding eta pattern with recalculated associated phi pattern ");
580 if (!ismatched && max_philevel > -1) {
583 ATH_MSG_DEBUG(
"No good candidate found, adding best phi pattern " << etalevel <<
" phi " << max_philevel);
587 ATH_MSG_DEBUG(
"NO COMBINED Candidate FOUND eta " << etalevel <<
" phi " << phibest);
601 std::vector<CandidatePatPair>&
candidates)
const {
609 std::unique_ptr<MuonPrdPatternCollection> combinedPatternCollection = std::make_unique<MuonPrdPatternCollection>();
610 int number_comb_patterns = 0;
611 for (
const auto& [etapattern, phipattern] :
candidates) {
614 std::unique_ptr<Muon::MuonPrdPattern> combinedpattern =
makeCombinedPattern(*phipattern, *etapattern);
615 if (combinedpattern) {
617 combinedPatternCollection->
push_back(combinedpattern.release());
618 number_comb_patterns++;
623 ATH_MSG_VERBOSE(
"No combined pattern, eta pattern split based on phi direction of eta pattern ");
626 if (splitetapatterns.empty()) {
627 combinedPatternCollection->
push_back(etapattern->clone());
629 for (
unsigned int i = 0;
i < splitetapatterns.size();
i++) {
630 if (splitetapatterns[
i].
second->numberOfContainedPrds() != 0) {
637 combinedPatternCollection->
push_back(etapattern->clone());
642 ATH_MSG_DEBUG(
"Number of combined patterns: " << number_comb_patterns <<
" Number of unmatched etapatterns: "
643 << combinedPatternCollection->
size() - number_comb_patterns);
645 return combinedPatternCollection;
677 std::unique_ptr<Muon::MuonPrdPattern> combinedpattern = std::make_unique<Muon::MuonPrdPattern>(
pos,
dir, std::move(comb_prds));
680 ATH_MSG_DEBUG(
"direction combined pattern: " << scphi.
cs * sctheta.
sn <<
" " << scphi.
sn * sctheta.
sn <<
" " << sctheta.
cs);
681 ATH_MSG_DEBUG(
"position combined pattern: " << x0 <<
" " << y0 <<
" " << z0_phi);
690 return combinedpattern;
693 ATH_MSG_DEBUG(
"Start Cleaning and Recalculating of Combined Pattern");
699 ATH_MSG_DEBUG(
"size before cleanup: " << size_before_cleanup);
706 if (size_before_cleanup == size_after_cleanup || size_after_cleanup == 0) {
708 return cleaneduppattern;
709 }
else if (size_after_cleanup < size_before_cleanup) {
710 combinedpattern = std::move(cleaneduppattern);
721 std::vector<PrdPatternPair> splitPatterns;
722 splitPatterns.reserve(2);
732 std::unique_ptr<Muon::MuonPrdPattern> phipattern1 = std::make_unique<Muon::MuonPrdPattern>(phipattern->
globalPosition(), dir1);
733 std::unique_ptr<Muon::MuonPrdPattern> etapattern1 = std::make_unique<Muon::MuonPrdPattern>(etapattern->
globalPosition(), dir1);
738 const double newphi =
phi +
M_PI;
747 std::unique_ptr<Muon::MuonPrdPattern> phipattern2 = std::make_unique<Muon::MuonPrdPattern>(phipattern->
globalPosition(), dir2);
748 std::unique_ptr<Muon::MuonPrdPattern> etapattern2 = std::make_unique<Muon::MuonPrdPattern>(etapattern->
globalPosition(), dir2);
756 const double dotprod = scphi.
apply(globalposhit.y(), globalposhit.x());
766 const double dotprod = scphi.
apply(globalposhit.y(), globalposhit.x());
773 splitPatterns.emplace_back(std::move(phipattern1), std::move(etapattern1));
774 splitPatterns.emplace_back(std::move(etapattern1), std::move(etapattern2));
775 return splitPatterns;
782 std::vector<PrdPatternPair> splitPatterns;
783 splitPatterns.reserve(2);
811 const double newphi =
phi +
M_PI;
821 std::unique_ptr<Muon::MuonPrdPattern> etapattern1 = std::make_unique<Muon::MuonPrdPattern>(globalpos, dir1);
822 std::unique_ptr<Muon::MuonPrdPattern> etapattern2 = std::make_unique<Muon::MuonPrdPattern>(globalpos, dir2);
823 std::unique_ptr<Muon::MuonPrdPattern> phipattern1, phipattern2{};
826 phipattern1 = std::make_unique<Muon::MuonPrdPattern>(globalpos, dir1);
827 phipattern2 = std::make_unique<Muon::MuonPrdPattern>(globalpos, dir2);
839 ATH_MSG_DEBUG(
" splitpoint, x: " << splitpoint[0] <<
" y: " << splitpoint[1] <<
" z: " << splitpoint[2]);
842 double d_x = scphi.
cs * sctheta.
sn;
843 double d_y = scphi.
sn * sctheta.
sn;
849 const double hitx = globalposhit.x();
850 const double hity = globalposhit.y();
851 const double hitz = globalposhit.z();
852 const double dotprod = hitx * d_x + hity * d_y + hitz * sctheta.
cs;
856 phipattern2->addPrd(prd);
865 const double hitx = globalposhit.x();
866 const double hity = globalposhit.y();
867 const double hitz = globalposhit.z();
868 const double dotprod = hitx * d_x + hity * d_y + hitz * sctheta.
cs;
883 splitPatterns.emplace_back(std::move(phipattern1), std::move(etapattern1));
884 splitPatterns.emplace_back(std::move(phipattern2), std::move(etapattern2));
886 return splitPatterns;
913 ATH_MSG_DEBUG(
"Pattern not through calorimeter -> do not split ");
927 const double posx = patternpos.x();
928 const double posy = patternpos.y();
929 const double posz = patternpos.z();
931 double invcurvature = 0.;
936 if (curvature > 2) invcurvature =
charge / curvature;
938 ATH_MSG_DEBUG(
"cleaned up pattern: phi " << phipattern <<
" theta: " << thetapattern <<
" position: " << posx <<
" " << posy <<
" "
942 std::unique_ptr<Muon::MuonPrdPattern> combinedpattern_cleaned =
952 double radius_pattern = globalposhit.perp();
953 double z0 = posz - radius_pattern * scthetapattern.
cs / scthetapattern.
sn;
957 const double scale =
std::max(1., globalposhit.mag() / 7000.);
960 <<
" dist xy " << distance_xy <<
" dist rz " << distance_rz <<
" scale: " <<
scale);
962 combinedpattern_cleaned->
addPrd(prd);
964 ATH_MSG_DEBUG(
"Hit discarded: " << hitid <<
" dis xy " << distance_xy <<
" dis rz " << distance_rz);
973 "cleaned up pattern is empty (should happen only when initially no phi "
974 "pattern found and phi hits are added by ascociation map)");
977 return combinedpattern_cleaned;
984 bool check_already_on_pattern)
const {
989 if (check_already_on_pattern) {
990 for (
unsigned int i = 0;
i <
size;
i++) {
hits.insert(muonpattern.
prd(
i)); }
992 std::vector<const Trk::PrepRawData*> phihits;
993 for (
unsigned int i = 0;
i <
size;
i++) {
997 if (!muoncluster)
continue;
998 EtaPhiHitAssocMap::const_iterator itr = phiEtaHitAssMap.find(prd);
1000 if (itr == phiEtaHitAssMap.end()) {
1003 std::copy_if(itr->second.begin(), itr->second.end(), std::back_inserter(phihits),
1005 return !check_already_on_pattern || hits.insert(phiHit).second;
1010 if (phihits.empty()) {
return nullptr; }
1012 std::unique_ptr<Muon::MuonPrdPattern> phipattern;
1014 double phi = 0., sin_phi = 0., cos_phi = 0.;
1021 sin_phi += scphihit.
sn;
1022 cos_phi += scphihit.
cs;
1024 phi = std::atan2(sin_phi, cos_phi);
1037 curvature * scphi.
sn * sctheta.
sn, curvature * sctheta.
cs};
1038 phipattern = std::make_unique<Muon::MuonPrdPattern>(globalpos, globaldir, phihits);
1043 std::unique_ptr<Muon::MuonPrdPattern> phipatternclean =
cleanPhiPattern(std::move(phipattern));
1046 phipatternclean.reset();
1048 return phipatternclean;
1064 std::array<double,4> old_pars{0};
1067 old_pars[1] = phiglobaldir.phi();
1069 const double theta_orig = etaglobaldir.theta();
1070 old_pars[2] = etaglobalpos.z() *
std::sin(theta_orig);
1071 old_pars[3] = theta_orig;
1073 if (phisize + etasize <= 1)
return old_pars;
1076 std::pair<double, double> rphi_start =
calculateR0Phi(phipattern, etapattern);
1078 std::pair<double, double> rphi =
calculateR0Phi(phipattern, etapattern, rphi_start.first);
1081 std::abs(
std::sin(etaglobaldir.phi() - phiglobaldir.phi())) < 0.15) {
1083 ATH_MSG_DEBUG(
"phi first: " << rphi_start.first <<
" phi second: " << rphi.first);
1084 ATH_MSG_DEBUG(
"phi etapattern: " << etaglobaldir.phi() <<
" phi phipattern: " << phiglobaldir.phi());
1087 const double phi = rphi.first;
1088 const double r0 = rphi.second;
1095 double av_radii{0.}, av_z{0.};
1097 for (
unsigned int i = 0;
i < etasize; ++
i) {
1100 av_radii += scphi.
apply(globalposhit.y(), globalposhit.x());
1101 av_z += globalposhit.z();
1105 av_radii /= etasize;
1110 for (
unsigned int i = 0;
i < etasize;
i++) {
1114 double radius = scphi.
apply(globalposhit.y(), globalposhit.x());
1115 double r_offset =
radius - av_radii;
1116 double z_offset = globalposhit.z() - av_z;
1117 double weight = r_offset * r_offset + z_offset * z_offset;
1126 ATH_MSG_VERBOSE(
"av_z : " << av_z <<
" av_radii: " << av_radii <<
" sumr: " << sumr <<
" sumz: " << sumz);
1127 if (std::abs(sumr) < 0.000001 || std::abs(sumz) < 0.000001)
return old_pars;
1129 double theta = std::atan2(sumr, sumz);
1139 std::array<double,4> new_pars {
r0,
phi,rz0,
theta};
1141 ATH_MSG_VERBOSE(
"updated parameters: r0: " << new_pars[0] <<
" phi: " << new_pars[1] <<
" rz0: " << new_pars[2]
1142 <<
" theta: " << new_pars[3]);
1143 ATH_MSG_VERBOSE(
"old parameters: r0: " << old_pars[0] <<
" phi: " << old_pars[1] <<
" rz0: " << old_pars[2] <<
" theta: " << old_pars[3]);
1147 for (
unsigned int i = 0;
i < phisize;
i++) {
1155 for (
unsigned int i = 0;
i < etasize;
i++) {
1163 for (
unsigned int i = 0;
i < etasize; ++
i) {
1166 double perp = scphi.
apply(globalposhit.y(),
1193 const double phi_etapattern = etaglobaldir.phi();
1198 const double phi_phipattern = phiglobaldir.phi();
1201 const double phi_error_inv = 1. / 20.;
1202 const double phi_error_inv2 = phi_error_inv * phi_error_inv;
1203 const double eta_error_inv = 1. / 400.;
1204 const double eta_error_inv2 = eta_error_inv * eta_error_inv;
1209 double sum_etax{0.}, sum_etay{0.}, sum_phix{0.}, sum_phiy{0.};
1213 for (
unsigned int i = 0;
i < etasize;
i++) {
1216 sum_etax += globalposhit.x();
1217 sum_etay += globalposhit.y();
1220 for (
unsigned int i = 0;
i < phisize;
i++) {
1223 sum_phix += globalposhit.x();
1224 sum_phiy += globalposhit.y();
1227 const double av_x = (eta_error_inv2 * sum_etax + phi_error_inv2 * sum_phix) / (eta_error_inv2 * etasize + phi_error_inv2 * phisize);
1228 const double av_y = (eta_error_inv2 * sum_etay + phi_error_inv2 * sum_phiy) / (eta_error_inv2 * etasize + phi_error_inv2 * phisize);
1234 double sumx {0.}, sumy {0.};
1238 double x_min {0.}, x_max {0.}, y_min {0.}, y_max {0.}, lever_min {0.}, lever_max{0.};
1240 for (
unsigned int i = 0;
i < etasize;
i++) {
1243 double x_offset = globalposhit.x() - av_x;
1244 double y_offset = globalposhit.y() - av_y;
1245 double height_squared = x_offset * x_offset + y_offset * y_offset;
1246 double weight = height_squared * eta_error_inv2;
1248 if (x_offset * scphi_est.
cs + y_offset * scphi_est.
sn < 0) {
sign = -1; }
1252 if (
sign == 1 && height_squared > lever_max) {
1253 lever_max = height_squared;
1254 x_max = globalposhit.x();
1255 y_max = globalposhit.y();
1256 }
else if (
sign == -1 && height_squared > lever_min) {
1257 lever_min = height_squared;
1258 x_min = globalposhit.x();
1259 y_min = globalposhit.y();
1263 for (
unsigned int i = 0;
i < phisize;
i++) {
1266 double x_offset = globalposhit.x() - av_x;
1267 double y_offset = globalposhit.y() - av_y;
1268 double height_squared = x_offset * x_offset + y_offset * y_offset;
1269 double weight = height_squared * phi_error_inv2;
1271 if (x_offset * scphi_est.
cs + y_offset * scphi_est.
sn < 0) {
sign = -1; }
1275 if (
sign == 1 && height_squared > lever_max) {
1276 lever_max = height_squared;
1277 x_max = globalposhit.x();
1278 y_max = globalposhit.y();
1279 }
else if (
sign == -1 && height_squared > lever_min) {
1280 lever_min = height_squared;
1281 x_min = globalposhit.x();
1282 y_min = globalposhit.y();
1286 ATH_MSG_VERBOSE(
"av_x : " << av_x <<
" av_y: " << av_y <<
" sumx: " << sumx <<
" sumy: " << sumy);
1288 if (std::abs(sumx) < 0.000001 || std::abs(sumy) < 0.000001) {
1295 if (std::hypot(x_max - x_min , y_max - y_min) < 2000) {
1296 ATH_MSG_VERBOSE(
"lever arm too small: av_x : " << std::sqrt((x_max - x_min) * (x_max - x_min) + (y_max - y_min) * (y_max - y_min))
1297 <<
" x_max: " << x_max <<
" x_min: " << x_min <<
" y_max: " << y_max
1298 <<
" y_min: " << y_min);
1302 double phi_fit = std::atan2(sumy, sumx);
1303 if (phi_fit > 0) phi_fit -=
M_PI;
1305 const double r0_fit = scphi.
apply(av_x, -av_y);
1307 return std::make_pair(phi_fit, r0_fit);
1311 double nhits =
pattern.numberOfContainedPrds();
1338 for (
unsigned int i = 0;
i < nhits;
i++) {
1341 int sign = (poshit.x() * scphi.
cs + poshit.y() * scphi.
sn > 0) ? 1 : -1;
1342 rz0 += poshit.z() * sctheta.
sn -
sign * sctheta.
cs * poshit.perp();
1345 if (nhits > 0) rz0 /= nhits;
1351 double phi = new_pars[1];
1352 double theta = new_pars[3];
1357 double x0 = new_pars[0] * scphi.
sn;
1358 double y0 = -new_pars[0] * scphi.
cs;
1359 double z0_phi = new_pars[2];
1360 double z0_eta = new_pars[2];
1361 if (std::abs(sctheta.
sn) > 1
e-7) {
1362 z0_phi = (new_pars[2] + new_pars[0] * sctheta.
cs) / sctheta.
sn;
1363 z0_eta = new_pars[2] / sctheta.
sn;
1369 ATH_MSG_VERBOSE(
"updatePatternsForCosmics() -- eta pattern "<<std::endl
1371 <<
" -- phi pattern "<<std::endl
1376 std::unique_ptr<Muon::MuonPrdPattern> updatedphipattern = std::make_unique<Muon::MuonPrdPattern>(globalPosPhi, globalDir, phipattern.
prepRawDataVec());
1377 std::unique_ptr<Muon::MuonPrdPattern> updatedetapattern = std::make_unique<Muon::MuonPrdPattern>(globalPosEta, globalDir, etapattern.
prepRawDataVec());
1379 return std::make_pair(std::move(updatedphipattern), std::move(updatedetapattern));
1385 std::unique_ptr<MuonPatternCombinationCollection> patterncombinations = std::make_unique<MuonPatternCombinationCollection>();
1390 ATH_MSG_DEBUG(
"phi: " << roadmom.phi() <<
" eta: " << roadmom.eta());
1391 ATH_MSG_DEBUG(
"x: " << roadpos.x() <<
" y: " << roadpos.y() <<
" z: " << roadpos.z());
1394 std::map<Identifier, std::vector<const Trk::PrepRawData*>> chamberMap;
1395 for (
unsigned int i = 0;
i < pit->numberOfContainedPrds(); ++
i) {
1399 std::vector<const Trk::PrepRawData*>& chambVec = chamberMap[moduleId];
1400 if (chambVec.empty()) chambVec.reserve(pit->numberOfContainedPrds());
1401 chambVec.push_back(prd);
1405 std::vector<Muon::MuonPatternChamberIntersect> mpciVec;
1406 mpciVec.reserve(chamberMap.size());
1408 for (
const auto& [moduleId, chambVec] : chamberMap) {
1413 patdire = roadmom.unit();
1420 mpciVec.push_back(mpci);
1427 patterncombinations->
push_back(combination);
1429 return patterncombinations;
1442 if (!
hits.count(pattern1->
prd(hitnr))) {
1456 if (candidate1.first.size() > candidate2.first.size() ||
1457 candidate1.second.size() > candidate2.second.size()) {
return false; }
1459 if (!candidate2.first.count(find_me)) {
return false; }
1462 if (candidate2.second.count(find_me)) {
return false; }
1485 ATH_MSG_VERBOSE(
"mdt " <<
k <<
" x: " << gpos.x() <<
" y: " << gpos.y() <<
" z: " << gpos.z());
1486 }
else if (!mdtprd) {
1490 ATH_MSG_VERBOSE(
"cluster " <<
k <<
" x: " << gpos.x() <<
" y: " << gpos.y() <<
" z: " << gpos.z());
1500 const double theta = olddir.theta();
1505 <<
" theta " <<
theta);
1512 std::unique_ptr<MuonHoughPattern> newpattern = std::make_unique<MuonHoughPattern>(
MuonHough::hough_xy);
1513 for (
unsigned int phihitnr = 0; phihitnr <
size; phihitnr++) { newpattern->
addHit(std::make_shared<MuonHoughHit>(phipattern->
prd(phihitnr))); }
1520 constexpr
int number_of_iterations = 4;
1521 std::array<double,number_of_iterations> cutvalues {1000., 500., 250., 125.};
1523 cutvalues[0] = 5000.;
1524 cutvalues[1] = 2500.;
1525 cutvalues[2] = 1250.;
1526 cutvalues[3] = 1250.;
1529 for (
int it = 0;
it < number_of_iterations; ++
it) {
1535 double max_dist = 0.;
1536 unsigned int max_i = 99999;
1537 for (
unsigned int i = 0;
i < newpattern->
size();
i++) {
1542 if (std::fabs(dist) > std::abs(max_dist)) {
1547 if (std::abs(max_dist) < cutvalues[
it]) {
1564 double thetanew = 0.;
1569 unsigned int nPatterns = newpattern->
size();
1570 for (
unsigned int i = 0;
i < nPatterns;
i++) { thetanew += newpattern->
getTheta(
i); }
1572 if (nPatterns > 0) thetanew /= nPatterns;
1576 double x0_new = r0_new * scphi.
sn;
1577 double y0_new = -r0_new * scphi.
cs;
1583 std::unique_ptr<Muon::MuonPrdPattern> cleanpattern = std::make_unique<Muon::MuonPrdPattern>(
pos,
dir);
1585 for (
unsigned int i = 0;
i < newpattern->
size();
i++) { cleanpattern->
addPrd(newpattern->
getPrd(
i)); }
1587 return cleanpattern;
1591 std::vector<CandidatePatPair>&
candidates,
bool add_asspattern,
1594 candidates.emplace_back(etapattern, phipattern);
1598 std::vector<PrdPatternPair> splitpatterns =
splitPatternsCylinder(phipattern.get(), etapattern.get());
1600 if (splitpatterns.empty()) {
1601 candidates.emplace_back(etapattern, phipattern);
1605 for (
auto& [phiPattern, etaPattern] : splitpatterns) {
1608 if (etaPattern->numberOfContainedPrds() == 0) {
1611 candidates.emplace_back(std::move(etaPattern), std::move(phiPattern));
1617 if (!add_asspattern) { return ;}
1618 std::unique_ptr<Muon::MuonPrdPattern> assphipattern =
makeAssPhiPattern(*etapattern, phiEtaHitAssMap,
true);
1620 if (!assphipattern) {
return;}
1632 std::unique_ptr<Muon::MuonPrdPattern>& cosmicPhiPattern = updatedpatterns.first;
1633 std::unique_ptr<Muon::MuonPrdPattern>& cosmicEtaPattern = updatedpatterns.second;
1635 std::vector<PrdPatternPair> splitpatterns_ass =
splitPatternsCylinder(cosmicPhiPattern.get(), cosmicEtaPattern.get());
1636 if (splitpatterns_ass.empty()) {
1637 candidates.emplace_back(std::move(cosmicEtaPattern), std::move(cosmicPhiPattern));
1642 for (
auto& [splitPhiPattern, splitEtaPattern] : splitpatterns_ass) {
1643 if (splitPhiPattern->numberOfContainedPrds() == 0 ||
1644 splitEtaPattern->numberOfContainedPrds() == 0) {
1647 candidates.emplace_back(std::move(splitEtaPattern), std::move(splitPhiPattern));
1655 std::map<CandidatePatPair, std::pair<PrepDataSet, PrepDataSet>> hitsMap;
1660 for (
unsigned int hitnr = 0; hitnr < (*it1).first->numberOfContainedPrds(); hitnr++) { etahits.insert((*it1).first->prd(hitnr)); }
1662 if ((*it1).second) {
1663 for (
unsigned int hitnr = 0; hitnr < (*it1).second->numberOfContainedPrds(); hitnr++) {
1664 phihits.insert((*it1).second->prd(hitnr));
1667 hitsMap.insert(std::make_pair((*
it1), std::make_pair(etahits, phihits)));
1671 std::pair<PrepDataSet, PrepDataSet>& hits1 = hitsMap[(*it1)];
1674 std::pair<PrepDataSet, PrepDataSet>& hits2 = hitsMap[(*it2)];
1675 if (
subset((hits2), (hits1))) {
1678 }
else if (
subset((hits1), (hits2))) {
1682 hits1 = hitsMap[(*it1)];