49 double cot(
double x) {
51 constexpr double dX = std::numeric_limits<float>::epsilon();
52 if (std::abs(
x) < dX || std::abs(
x -
M_PI) < dX)
return std::numeric_limits<float>::max();
54 return std::tan(M_PI_2 -
x);
56 template <
typename T>
constexpr T absmax(
const T&
a,
const T& b) {
57 return std::abs(
a) > std::abs(b) ?
a :
b;}
81 return StatusCode::SUCCESS;
85 const std::vector<const MdtDriftCircleOnTrack*>& mdts,
86 const std::vector<const MuonClusterOnTrack*>& clusters,
bool hasPhiMeasurements,
88 const EventContext& ctx = Gaudi::Hive::currentContext();
94 ATH_MSG_DEBUG(
"In find, passed " << mdts.size() <<
" MDTs & "<<clusters.size()<<
" clusters");
96 if (mdts.size() < 3)
return;
100 if (!firstRot) {
return; }
124 double chamber_angleYZ = std::atan2(dirCh.z(), dirCh.y());
127 double dotprod = globalDirCh.perp() * std::sin(roaddir2.theta()) + globalDirCh.z() * std::cos(roaddir2.theta());
128 if (dotprod < 0) roaddir2 = -roaddir2;
133 double road_angleXZ = std::atan2(d.z(), d.x());
134 double road_angleYZ = std::atan2(d.z(), d.y());
136 if (!hasPhiMeasurements) road_angleXZ =
M_PI;
138 << isEndcap <<
" central phi " << detEl->
center().phi() <<
" r " << detEl->
center().perp()
139 <<
" z " << detEl->
center().z());
154 if (msgLvl(MSG::VERBOSE)) {
155 std::stringstream sstr{};
158 ATH_MSG_VERBOSE(
" adding mdts " << mdts.size()<<std::endl<<sstr.str());
162 std::set<Identifier> chamberSet;
163 double phimin{-9999}, phimax{9999};
168 std::shared_ptr<const TrkDriftCircleMath::ChamberGeometry> multiGeo;
170 ATH_MSG_VERBOSE(
" using chamber geometry with #chambers " << chamberSet.size());
172 std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos{};
175 geos.reserve(chamberSet.size());
181 multiGeo = std::make_unique<TrkDriftCircleMath::MdtMultiChamberGeometry>(geos);
187 if (sinAngleCut > 0)
angle = sinAngleCut;
193 if (msgLvl(MSG::VERBOSE)) {
194 std::stringstream sstr{};
195 unsigned int seg_n{0};
197 constexpr double toDeg = 1./Gaudi::Units::degree;
198 sstr<<
"Segment number "<<seg_n<<
" is at ("<<seg.line().x0()<<
","<<seg.line().y0()<<
") pointing to "<<seg.line().phi()*toDeg<<
" chi2: "<<
199 (seg.chi2()/seg.ndof())<<
"("<<seg.ndof()<<
")"<<std::endl;
200 sstr<<
"Mdt measurements: "<<seg.dcs().size()<<std::endl;
202 sstr<<
" **** "<<
m_printer->print(*mdt_meas.rot());
203 sstr<<
" ("<<mdt_meas.state()<<
")"<<std::endl;
205 sstr<<
"Cluster measurements "<<seg.clusters().size()<<std::endl;
207 sstr<<
" ---- "<<
m_printer->print(*clus.rot())<<std::endl;
212 ATH_MSG_VERBOSE(
"Found " << segs.size() <<
" segments "<<std::endl<<sstr.str());
216 if (segs.empty()) {
return; }
219 segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax);
221 std::unique_ptr<MuonSegment> segment =
createSegment(ctx, seg, chid, roadpos, roaddir2, mdts, hasPhiMeasurements, sInfo, beta);
222 if (segment) segColl->
push_back(segment.release());
229 const std::vector<const MdtDriftCircleOnTrack*>& mdts,
bool hasPhiMeasurements,
235 static constexpr std::array<ChIndex ,4> statWithField{ChIndex::BIL, ChIndex::BML, ChIndex::BMS, ChIndex::BOL};
237 std::ranges::find(statWithField,
chIndex) != statWithField.end();
245 ATH_MSG_DEBUG(
"New segment: chi2 " << segment.
chi2() <<
" ndof " << segment.
ndof() <<
" line " << line.position().x() <<
","
246 << line.position().y() <<
" phi " << line.phi() <<
" associated clusters "
256 if (hasPhiMeasurements) {
260 double cphi = lroaddir.x();
264 lxroad = lroadpos.x() + (-lroadpos.y() + line.position().x()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
267 lxroad = lroadpos.x() + (-lroadpos.z() + line.position().y()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
270 double shortestTubeLen = 1e9;
279 if (tubelen < shortestTubeLen) shortestTubeLen = tubelen;
282 if (std::abs(lxroad) > shortestTubeLen) {
283 ATH_MSG_DEBUG(
"coordinates far outside chamber! using global position of first hit ");
284 if (lxroad < 0.) shortestTubeLen *= -1.;
285 lxroad = shortestTubeLen;
288 lxroad = (sInfo.
globalTrans * mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x();
292 Amg::Vector3D lpos(lxroad, line.position().x(), line.position().y());
299 surfaceTransform.pretranslate(gpos);
300 double surfDim = 500.;
301 std::unique_ptr<Trk::PlaneSurface> surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
305 double linephi = line.phi();
312 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> > rioDistVec;
315 std::set<Identifier> deltaVec;
316 std::set<Identifier> outoftimeVec;
319 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>> garbage_collector;
330 std::abs(segment.
line().
x0() -
result.line().x0()) > 0.01 ||
331 std::abs(segment.
line().
y0() -
result.line().y0()) > 0.01) {
333 linephi =
result.line().phi();
334 lpos[1] =
result.line().position().x();
335 lpos[2] =
result.line().position().y();
340 surfaceTransform.pretranslate(gpos);
341 surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
351 surf->globalToLocalDirection(gdir, segLocDir);
361 if (std::min(std::abs(diff_phi), std::abs( std::abs(diff_phi) -
M_PI)) > 1.e-3 ||
362 std::min(std::abs(diff_prec), std::abs(std::abs(diff_prec) -
M_PI)) > 1.e-3) {
363 ATH_MSG_WARNING(
" ALARM updated angles wrong: diff phi " << diff_phi <<
" prec " << diff_prec <<
" phi rdir " << roaddir2.phi()
364 <<
" gdir " << gdir.phi() <<
" lphi " << linephi <<
" seg "
369 std::pair<std::pair<int, int>,
bool> netaPhiHits =
372 if (rioDistVec.empty()){
378 auto meas_for_fit = [&rioDistVec] () {
379 std::vector<const Trk::MeasurementBase*> out{};
380 out.reserve(rioDistVec.size());
382 for (
const std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& ele : rioDistVec) out.push_back(ele.second.get());
387 double dlocx{1000.}, dangleXZ{1000.}, qoverp{-99999.}, dqoverp{-99999.};
388 bool hasMeasuredCoordinate =
false;
390 ATH_MSG_DEBUG(
" distance between first and last phi hit sufficient to perform 4D fit: phi " << gdir.phi() <<
" theta "
393 std::unique_ptr<Trk::Track> track{
m_segmentFitter->fit(gpos, gdir, *surf, meas_for_fit())};
396 if (isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance()) {
397 qoverp = track->perigeeParameters()->parameters()[
Trk::qOverP];
400 hasMeasuredCoordinate =
true;
403 updatedCov.setZero();
404 m_segmentFitter->updateSegmentParameters(*track, *surf, segLocPos, segLocDir, updatedCov);
413 surf->localToGlobal(segLocPos, gdir, gpos);
414 surf->localToGlobalDirection(segLocDir, gdir);
416 if (track->measurementsOnTrack() && rioDistVec.size() != track->measurementsOnTrack()->size()) {
417 if (track->measurementsOnTrack()->empty()) {
421 ATH_MSG_DEBUG(
" ROT vector size changed after fit, updating ");
422 garbage_collector = std::move(rioDistVec);
423 rioDistVec.reserve(track->measurementsOnTrack()->size());
428 if (!firstPars) firstPars = pars;
434 double dist = (pars->position() - firstPars->
position()).dot(firstPars->
momentum().unit());
435 rioDistVec.emplace_back(dist, meas->
uniqueClone());
440 netaPhiHits.second =
false;
448 surf->localToGlobal(segLocPos, gpos, gpos);
449 surf->localToGlobalDirection(segLocDir, gdir);
450 hasMeasuredCoordinate =
true;
456 if (msgLvl(MSG::DEBUG)) {
457 std::vector<const Trk::MeasurementBase*> debug_meas = meas_for_fit();
458 ATH_MSG_DEBUG(
" number of hits " << debug_meas.size() <<
" of which trigger " << netaPhiHits.first.first <<
" eta and "
459 << netaPhiHits.first.second <<
" phi ");
467 <<
" radius " << std::setw(6) << mdt->
driftRadius() <<
" time " << std::setw(6) << mdt->
driftTime());
480 std::vector<Identifier> holeVec =
calculateHoles(ctx, chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec);
483 if (!outoftimeVec.empty()) holeVec.insert(holeVec.end(), std::make_move_iterator(outoftimeVec.begin()),
484 std::make_move_iterator(outoftimeVec.end()));
496 bool hasFittedT0 =
false;
497 double fittedT0{0}, errorFittedT0{1.};
502 errorFittedT0 = segment.
t0Error();
503 }
else if (dcslFitter &&
result.hasT0Shift()) {
504 fittedT0 =
result.t0Shift();
505 errorFittedT0 =
result.t0Error();
512 std::unique_ptr<MuonSegment> msegment;
513 if (isCurvedSegment) {
514 if (qoverp == -99999.) {
515 double charge = gpos.z() * std::tan(gdir.theta());
518 constexpr double BILALPHA(28.4366), BMLALPHA(62.8267), BMSALPHA(53.1259), BOLALPHA(29.7554);
521 dqoverp = M_SQRT2 * segment.
dtheta() / BILALPHA;
522 }
else if (
chIndex == ChIndex::BML) {
524 dqoverp = M_SQRT2 * segment.
dtheta() / BMLALPHA;
525 }
else if (
chIndex == ChIndex::BMS) {
527 dqoverp = M_SQRT2 * segment.
dtheta() / BMSALPHA;
528 }
else if (
chIndex == ChIndex::BOL) {
530 dqoverp = M_SQRT2 * segment.
dtheta() / BOLALPHA;
534 covMatrix.setIdentity();
535 covMatrix(0, 0) = dlocx * dlocx;
536 covMatrix(1, 1) = segment.
dy0() * segment.
dy0();
537 covMatrix(2, 2) = dangleXZ * dangleXZ;
539 covMatrix(4, 4) = dqoverp * dqoverp;
541 std::vector<Trk::DefinedParameter> defPars;
544 defPars.emplace_back(gdir.phi(),
Trk::phi);
545 defPars.emplace_back(gdir.theta(),
Trk::theta);
548 msegment = std::make_unique<MuonSegment>(
549 std::move(segLocPar),
550 std::move(covMatrix),
558 covMatrix.setIdentity();
559 covMatrix(0, 0) = dlocx * dlocx;
560 covMatrix(1, 1) = segment.
dy0() * segment.
dy0();
561 covMatrix(2, 2) = dangleXZ * dangleXZ;
564 std::make_unique<MuonSegment>(segLocPos,
566 std::move(covMatrix),
573 if (hasFittedT0) msegment->setT0Error(fittedT0, errorFittedT0);
578 if (msgLvl(MSG::DEBUG)) {
584 if (segmentQuality < 0) {
return nullptr; }
589 std::vector<const MdtDriftCircleOnTrack*> mdts;
590 std::vector<const MuonClusterOnTrack*> clusters;
596 if (!mdt) {
ATH_MSG_WARNING(
"failed dynamic_cast, not a MDT but hit has MDT id!!!"); }
600 if (!clus) {
ATH_MSG_WARNING(
"failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); }
601 clusters.push_back(clus);
604 find(mdts, clusters, segColl);
609 if (mdts.empty())
return;
614 bool hasPhiMeasurements =
false;
617 find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl);
621 const std::vector<const Trk::RIO_OnTrack*>& rios2)
const {
622 std::vector<const Trk::RIO_OnTrack*> rios = rios1;
623 rios.insert(rios.end(), rios2.begin(), rios2.end());
629 bool hasPhiMeasurements,
double momentum)
const {
631 std::vector<const MdtDriftCircleOnTrack*> all_mdts;
632 for (
const std::vector<const MdtDriftCircleOnTrack*>& circle_vec : mdts) { std::copy(circle_vec.begin(), circle_vec.end(), std::back_inserter(all_mdts)); }
635 std::vector<const MuonClusterOnTrack*> all_clus;
636 for (
const std::vector<const MuonClusterOnTrack*>& clus_vec : clusters) { std::copy(clus_vec.begin(), clus_vec.end(), std::back_inserter(all_clus)); }
640 find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.
deltaEta());
649 double scaleMax = 5.;
651 scale = std::min(scaleMax, 1. + curvature / 10000);
652 ATH_MSG_DEBUG(
" rescaled errors " << scale <<
" curvature " << curvature);
657 if (!hasPhiMeasurements) {
658 double phiScale = 1.;
660 int stRegion =
m_idHelperSvc->mdtIdHelper().stationRegion(
id);
663 else if (stRegion == 1)
665 else if (stRegion == 2)
669 scale = std::sqrt(scale*scale + phiScale*phiScale);
670 ATH_MSG_DEBUG(
" rescaled error for missing phi road " << scale);
686 if (
stName[1] ==
'I')
return true;
696 if (clusters.empty())
return {};
702 clVec.reserve(clusters.size());
710 if (phiVec.back().corrupt()) phiVec.pop_back();
713 if (clVec.back().corrupt()) clVec.pop_back();
722 if (clusters.empty())
return {};
733 gasGapHitMap[chId][gasGapId].first.push_back(clus);
735 gasGapHitMap[chId][gasGapId].second.push_back(clus);
744 spacePoints.reserve(20);
747 for (
const auto& [
id, gasGapHits] : chIdHitMap) {
750 std::copy(std::make_move_iterator(cls.first.begin()),
751 std::make_move_iterator(cls.first.end()), std::back_inserter(spacePoints));
752 std::copy(std::make_move_iterator(cls.second.begin()),
753 std::make_move_iterator(cls.second.end()), std::back_inserter(phiVec));
756 return std::make_pair(std::move(spacePoints), std::move(phiVec));
761 bool isEndcap =
m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first);
763 ATH_MSG_VERBOSE(
" creating Space points for " << gasGapHitMap.size() <<
" gas gaps ");
765 for (
const auto& [gasGapId, etaPhiHits] : gasGapHitMap) {
767 std::vector<bool> flagPhihit(etaPhiHits.second.size(), 0);
773 << etaPhiHits.second.size());
777 if (etaHit->
identify() == prevEtaId)
continue;
784 bool foundSP =
false;
790 if (phiHit->
identify() == prevPhiId)
continue;
796 if (
sp.corrupt())
continue;
797 spacePoints.push_back(std::move(
sp));
800 flagPhihit[phi_idx] =
true;
806 if (
sp.corrupt())
continue;
807 spacePoints.push_back(std::move(
sp));
811 if (
sp.corrupt())
continue;
813 flagPhihit = std::vector<bool>(etaPhiHits.second.size(), 1);
814 spacePoints.push_back(std::move(
sp));
820 for (
unsigned int i = 0; i < flagPhihit.size(); ++i) {
821 if (flagPhihit[i])
continue;
824 if (etaPhiHits.second[i]->identify() == prevPhiId)
continue;
825 prevPhiId = etaPhiHits.second[i]->identify();
828 if (
sp.corrupt())
continue;
829 phiVec.push_back(std::move(
sp));
831 }
else if (etaPhiHits.first.empty() && !etaPhiHits.second.empty()) {
834 if (
sp.corrupt())
continue;
835 phiVec.push_back(std::move(
sp));
839 ATH_MSG_VERBOSE(
" Creating space points, number of gas-gaps " << gasGapHitMap.size() <<
" space points " << spacePoints.size());
841 return std::make_pair(std::move(spacePoints), std::move(phiVec));
847 double error{1.}, lpx{0.}, lpy{0.};
857 }
else if (!phiHit) {
860 }
else if (etaHit && phiHit) {
864 std::vector<const MuonClusterOnTrack*> phiVec{phiHit};
869 if (std::abs(
error) < 0.001) {
879 double error{1.}, lpx{0.}, lpy{0.};
885 }
else if (!phiHit) {
888 }
else if (etaHit && phiHit) {
897 lpx = lSpacePoint.x();
898 lpy = lSpacePoint.y();
900 if (
error <= std::numeric_limits<double>::epsilon()) {
909 if (std::abs(
error) < 0.001) {
918 const std::vector<const MuonClusterOnTrack*>& phiHits)
const {
920 std::vector<const MuonClusterOnTrack*> cleanPhihits;
921 cleanPhihits.reserve(phiHits.size());
923 double error{1.}, lpx{0.}, lpy{0.};
926 lpx = phiHits.front()->localParameters()[
Trk::locX];
932 if (clus->identify() == prevId)
continue;
933 prevId = clus->identify();
934 cleanPhihits.push_back(clus);
936 }
else if (phiHits.empty()) {
939 }
else if (etaHit && !phiHits.empty()) {
946 double minPos{1e9}, maxPos{-1e9};
952 if (phiHit->identify() == prevId)
continue;
953 prevId = phiHit->identify();
959 minPos = std::min(minPos, lpy);
960 maxPos = std::max(maxPos, lpy);
962 cleanPhihits.push_back(phiHit);
965 if (cleanPhihits.size() > 1)
966 ATH_MSG_DEBUG(
" multiple phi hits: nhits " << cleanPhihits.size() <<
" cl width " << maxPos - minPos);
971 if (std::abs(
error) < 0.001) {
982 const int chPhi =
m_idHelperSvc->mdtIdHelper().stationPhi(chid);
986 cls.reserve(spVec.size());
1015 cls.emplace_back(lp, clust.error, clid, meas,
index);
1021 std::set<Identifier>& chamberSet,
double& phimin,
double& phimax,
1025 dcs.reserve(mdts.size());
1027 bool firstMdt =
true;
1035 Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition();
1038 double r = rot->localParameters()[
Trk::locR];
1046 double preciseError = dr;
1053 phimin = tubeEnds.
phimin;
1054 phimax = tubeEnds.
phimax;
1061 << rot->driftTime() <<
" r " <<
r <<
" dr " << dr <<
" phi range " << tubeEnds.
phimin <<
" "
1062 << tubeEnds.
phimax<<
" precise error "<<preciseError);
1063 dcs.push_back(std::move(dc));
1065 chamberSet.insert(elId);
1067 ++dcStatistics[rot->prepRawData()->detectorElement()];
1098 ATH_MSG_ERROR(
"Null pointer to the read MuonDetectorManager conditions object");
1114 firstTubeMl1 = gToStation * (detEl2->
surface(firstIdml1).center());
1124 firstTubeMl0 = gToStation * (detEl1->
surface(firstIdml0).center());
1137 double tubeDist = (secondTubeMl0 - firstTubeMl0).
y();
1138 double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).
y();
1139 double layDist = (firstTubeMl0lay1 - firstTubeMl0).
z();
1141 TrkDriftCircleMath::MdtChamberGeometry mdtgeo(chid,
m_idHelperSvc.get(), nml, nlay, ntube1, ntube2, firstTube0, firstTube1, tubeDist, tubeStage,
1144 if (msgLvl(MSG::VERBOSE)) mdtgeo.
print(msgStream());
1152 std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec,
1153 std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec,
double beta)
const {
1162 double ml2phi = line.phi() - segment.
deltaAlpha();
1167 double chamberMidPtY = (ml1LocPos.
y() + ml2LocPos.
y()) / 2.0;
1173 toLineml2 = tmptoLine;
1201 posAlong[1] = pointOnLineAMDB.
x();
1202 posAlong[2] = pointOnLineAMDB.
y();
1209 ATH_MSG_WARNING(
" dynamic cast to StraightLineSurface failed for mdt!!! ");
1220 std::unique_ptr<MdtDriftCircleOnTrack> nonconstDC;
1224 nonconstDC.reset(
m_mdtCreator->createRIO_OnTrack(*riodc->
prepRawData(), mdtGP, &gdir, 0.,
nullptr, beta, 0.));
1225 if (hasT0)
ATH_MSG_WARNING(
"Attempted to change t0 without a properly configured MDT creator tool. ");
1239 dcit.driftState(), dcit.id(),
1242 dcit = std::move(new_dc_on_track);
1245 if (msgLvl(MSG::VERBOSE)) {
1246 double shift = riodc->
driftTime() - nonconstDC->driftTime();
1247 ATH_MSG_VERBOSE(
" t0 shift " << segment.
t0Shift() <<
" from hit " << shift <<
" recal " << nonconstDC->driftRadius()
1248 <<
" t " << nonconstDC->driftTime() <<
" from fit " << dcit.r() <<
" old "
1250 if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit.r())) > 0.1 && nonconstDC->driftRadius() < 19. &&
1251 nonconstDC->driftRadius() > 1.) {
1257 double dist = pointOnHit.
x();
1258 rioDistVec.emplace_back(dist, std::move(nonconstDC));
1278 bool operator()(
const std::pair<double, DCMathSegmentMaker::Cluster2D>& d1,
1279 const std::pair<double, DCMathSegmentMaker::Cluster2D>& d2) {
1280 return std::abs(d1.first) < std::abs(d2.first);
1286 double phimin,
double phimax, std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec)
const {
1289 typedef std::vector<ChamberData> ChamberDataVec;
1290 ChamberDataVec chamberDataVec;
1295 std::pair<std::pair<int, int>,
bool> netaPhiHits(std::make_pair(0, 0),
false);
1296 if (segment.
clusters().empty())
return netaPhiHits;
1298 std::vector<const Trk::MeasurementBase*> phiHits;
1304 std::set<Identifier> detElOnSegments;
1305 std::set<MuonStationIndex::PhiIndex> phiIndices;
1307 ATH_MSG_DEBUG(
" Associating clusters: " << segment.
clusters().size() <<
" number of space points " << spVecs.first.size());
1312 const Cluster2D& spacePoint = spVecs.first[clust.index()];
1316 ATH_MSG_DEBUG(
" Found corrupt space point: index " << clust.index());
1325 ATH_MSG_DEBUG(
" Inconsistent phi angle, dropping space point: phi " << spacePoint.
globalPos.phi() <<
" range " << phimin
1333 if (chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.
detElId) {
1334 detElOnSegments.insert(spacePoint.
detElId);
1335 chamberDataVec.emplace_back(spacePoint.
detElId);
1337 phiIndices.insert(phiIndex);
1341 ChamberData& chamber = chamberDataVec.back();
1344 if (spacePoint.
detElId == chamber.id) {
1346 if (chamber.data.empty() || chamber.data.back().id != spacePoint.
gasGapId) {
1347 chamber.data.emplace_back(spacePoint.
gasGapId);
1353 gasGap.data.emplace_back(resPull.second, spacePoint);
1357 double posFirstPhiStation{FLT_MAX}, posLastPhiStation{0.};
1360 for (ChamberData& chamb : chamberDataVec) {
1362 std::list<const Trk::PrepRawData*> etaClusterVec{}, phiClusterVec{};
1363 std::set<Identifier> etaIds;
1370 double bestPull = std::abs(gasGap.data.front().first);
1373 unsigned int nassociatedSp = 0;
1374 GasGapData::EntryVec::const_iterator cl_it = gasGap.data.begin();
1375 while (cl_it != gasGap.data.end() && std::abs(cl_it->first) - bestPull < 1.) {
1380 << std::abs(cl_it->first) <<
" distance to segment " << dist <<
" phi "
1381 <<
sp.globalPos.phi());
1385 if (!etaIds.count(
sp.etaHit->identify())) {
1386 etaIds.insert(
sp.etaHit->identify());
1389 etaClusterVec.push_back(
sp.etaHit->prepRawData());
1391 rioDistVec.emplace_back(dist,
sp.etaHit->uniqueClone());
1392 ++netaPhiHits.first.first;
1396 if (!
sp.phiHits.empty()) {
1399 std::transform(
sp.phiHits.begin(),
sp.phiHits.end(), std::back_inserter(phiClusterVec),
1401 return clus->prepRawData();
1406 rioDistVec.emplace_back(dist, phi_hit->
uniqueClone());
1407 ++netaPhiHits.first.second;
1408 phiHits.push_back(phi_hit);
1412 posFirstPhiStation = std::min(phiPos, posFirstPhiStation);
1413 posLastPhiStation = std::max(phiPos, posLastPhiStation);
1415 if (
sp.phiHits.size() > 1) refit =
false;
1427 if (!etaClusterVec.empty()) {
1428 std::unique_ptr<const CompetingMuonClustersOnTrack> etaCompCluster =
m_compClusterCreator->createBroadCluster(etaClusterVec, 0.);
1429 if (!etaCompCluster) {
1430 ATH_MSG_DEBUG(
" failed to create competing ETA ROT " << etaClusterVec.size());
1432 double dist =
distanceToSegment(segment, etaCompCluster->globalPosition(), gToStation);
1433 ++netaPhiHits.first.first;
1434 if (msgLvl(MSG::VERBOSE)) {
1436 for (
unsigned int i = 0; i < etaCompCluster->containedROTs().size(); ++i) {
1438 " content: " <<
m_idHelperSvc->toString(etaCompCluster->containedROTs()[i]->identify()));
1441 rioDistVec.emplace_back(dist, std::move(etaCompCluster));
1448 if (!phiClusterVec.empty()) {
1449 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster =
m_compClusterCreator->createBroadCluster(phiClusterVec, 0.);
1450 if (!phiCompCluster) {
1451 ATH_MSG_DEBUG(
" failed to create competing PHI ROT " << phiClusterVec.size());
1453 double dist =
distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1454 phiHits.push_back(phiCompCluster.get());
1456 ++netaPhiHits.first.second;
1458 if (msgLvl(MSG::VERBOSE)) {
1460 for (
unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1462 " content: " <<
m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1468 double phiPos = isEndcap ? std::abs(phiCompCluster->globalPosition().z()) :
1469 phiCompCluster->globalPosition().perp();
1470 posFirstPhiStation = std::min(phiPos,posFirstPhiStation);
1471 posLastPhiStation = std::max(phiPos,posLastPhiStation);
1472 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1483 std::map<Identifier, std::list<const Trk::PrepRawData*> > phiClusterMap;
1485 std::set<const MuonClusterOnTrack*> selectedClusters;
1486 std::vector<const Cluster2D*> phiClusters;
1487 phiClusters.reserve(spVecs.second.size());
1490 for (
const Cluster2D& phi_clus :spVecs.second) {
1495 phiClusters.push_back(&phi_clus);
1496 selectedClusters.insert(phi_clus.
phiHit);
1499 unsigned int recoveredUnassociatedPhiHits(0);
1503 for (
const Cluster2D& rpc_clust : spVecs.first) {
1508 if (detElOnSegments.count(rpc_clust.
detElId))
continue;
1512 if (phiIndices.count(phiIndex))
continue;
1514 bool wasFound =
false;
1517 if (!selectedClusters.insert(phi_hit).second) {
1524 if (erase_me == phi_hit)
break;
1525 selectedClusters.erase(erase_me);
1530 if (wasFound)
continue;
1533 phiClusters.push_back(&rpc_clust);
1534 ++recoveredUnassociatedPhiHits;
1538 unsigned int addedPhiHits(0);
1539 for (
const Cluster2D* phi_clus : phiClusters) {
1543 if (detElOnSegments.count(detElId))
continue;
1547 if (phiIndices.count(phiIndex))
continue;
1554 double residual = resWithSegment.
residual(cl);
1555 double segError = std::sqrt(resWithSegment.
trackError2(cl));
1564 bool inBounds = std::abs(residual) < 0.5 * stripLength + 2. + segError;
1565 if (msgLvl(MSG::DEBUG)) {
1567 <<
" pos y " << cl.position().y() <<
" : residual " << residual <<
" strip half length "
1568 << 0.5 * stripLength <<
" segment error " << segError);
1576 std::list<const Trk::PrepRawData*>& cham_hits{phiClusterMap[detElId]};
1577 std::transform(phi_clus->
phiHits.begin(), phi_clus->
phiHits.end(), std::back_inserter(cham_hits),
1579 return clus->prepRawData();
1585 for (
const auto& [phi_id, prds] : phiClusterMap) {
1591 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster =
m_compClusterCreator->createBroadCluster(prds, 0.);
1592 if (!phiCompCluster) {
1593 ATH_MSG_DEBUG(
" failed to create competing PHI ROT " << prds.size());
1595 double dist =
distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1600 <<
" distance to segment " << dist);
1603 phiHits.push_back(phiCompCluster.get());
1604 ++netaPhiHits.first.second;
1606 if (msgLvl(MSG::VERBOSE)) {
1608 <<
" distance to segment " << dist);
1609 for (
unsigned int i = 0; i < phiCompCluster->containedROTs().size(); ++i) {
1611 " content: " <<
m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1614 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1617 ATH_MSG_VERBOSE(
"Added " << addedPhiHits <<
" unass phi hits out of " << spVecs.second.size()
1618 <<
" phi hits without eta hit and " << recoveredUnassociatedPhiHits <<
" with unassociated eta hit ");
1622 double phiDistanceMax = posLastPhiStation - posFirstPhiStation;
1623 if (isEndcap && phiDistanceMax < 1000.)
1625 else if (phiDistanceMax < 400.)
1628 netaPhiHits.second = refit;
1636 double cos_sinLine = cot(line.phi());
1644 double delta_y = lpos.
y() - line.position().y();
1652 return pointOnHit.
x();
1656 std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) {
1661 rioVec.
reserve(rioDistVec.size());
1662 for (std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) { rioVec.
push_back(std::move(rdit.second)); }
1671 double cos_sinLine = cot(line.phi());
1678 double delta_y = lpos.
y() - line.position().y();
1684 double residual = lpos.
x() - lineSurfaceIntersect.
x();
1685 double pull = residual / spacePoint.
error;
1686 return std::make_pair(residual, pull);
1691 std::set<Identifier>& outoftimeVec,
const std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec)
const {
1694 if (!InterSectSvc.
isValid()) {
1695 ATH_MSG_ERROR(
"Null pointer to the read MuonDetectorManager conditions object");
1701 const MuonStationIntersect intersect = InterSectSvc->tubesCrossedByTrack(MuonDetMgr, chid, gpos, gdir);
1704 std::set<Identifier> hitsOnSegment, chambersOnSegment;
1705 int firstLayer{-1}, lastLayer{-1};
1706 for (
const std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) {
1711 if (firstLayer == -1)
1716 hitsOnSegment.insert(
id);
1721 if (firstLayer > lastLayer) {
std::swap(firstLayer, lastLayer); }
1722 ATH_MSG_VERBOSE(
" Tube layer ranges: " << firstLayer <<
" -- " << lastLayer <<
" crossed tubes "
1723 << intersect.tubeIntersects().size());
1725 std::vector<Identifier> holeVec;
1727 if (!chambersOnSegment.count(
m_idHelperSvc->chamberId(tint.tubeId))) {
1728 ATH_MSG_VERBOSE(
" chamber not on segment, not counting tube " << tint.rIntersect <<
" l " << tint.xIntersect <<
" "
1736 bool notBetweenHits = layer < firstLayer || layer > lastLayer;
1737 double distanceCut = hasMeasuredCoordinate ? -20 : -200.;
1739 if (notBetweenHits && (std::abs(tint.rIntersect) > innerRadius || (!
m_allMdtHoles && tint.xIntersect > distanceCut))) {
1740 ATH_MSG_VERBOSE(
" not counting tube: distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1745 if (hitsOnSegment.count(tint.tubeId)) {
1746 ATH_MSG_VERBOSE(
" tube on segment: distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1752 if (deltaVec.count(tint.tubeId)) {
1753 ATH_MSG_VERBOSE(
" removing delta, distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1760 ATH_MSG_VERBOSE(
" found and removed delta, distance to wire " << tint.rIntersect <<
" dist to tube end "
1761 << tint.xIntersect <<
" "
1766 ATH_MSG_VERBOSE((outoftimeVec.count(tint.tubeId) ?
"Out-of-time" :
"hole") <<
" distance to wire "
1767 << tint.rIntersect <<
" dist to tube end " << tint.xIntersect <<
" "
1768 <<
m_idHelperSvc->toString(tint.tubeId)<<(notBetweenHits ?
"outside hits" :
"between hits"));
1770 holeVec.push_back(tint.tubeId);
1787 if (!collptr)
return nullptr;
1789 if (prd->identify() ==
id)
return prd;
1795 const std::vector<const MdtDriftCircleOnTrack*>& mdts)
const {
1796 int hitsInChamberWithMostHits = 0;
1797 std::map<Identifier, int> hitsPerChamber;
1798 int currentSector = -1;
1809 if (currentSector == -1) {
1810 currentSector = sector;
1811 }
else if (sector != currentSector) {
1814 int& hitsInCh = hitsPerChamber[chId];
1816 if (hitsInCh > hitsInChamberWithMostHits) {
1817 hitsInChamberWithMostHits = hitsInCh;
1818 rotInChamberWithMostHits = rot;
1821 return rotInChamberWithMostHits;
1825 const std::vector<DCMathSegmentMaker::HitInXZ>& hits)
const {
1829 for (
const HitInXZ& hit : hits) {
1830 bool outBounds =
false;
1831 double locExX = xline + dXdZ * (hit.z - zline);
1832 if (hit.isMdt && (locExX < hit.xmin - 1. || locExX > hit.xmax + 1.)) {
1835 if (!msgLvl(MSG::DEBUG))
break;
1838 if (outBounds && msgLvl(MSG::DEBUG)) {
1840 << std::setw(6) << (
int)hit.z <<
") ex pos " << std::setw(6) << (
int)locExX <<
" min " << std::setw(6)
1841 << (
int)hit.xmin <<
" max " << std::setw(6) << (
int)hit.xmax <<
" phimin " << std::setw(6)
1842 << hit.phimin <<
" phimax " << std::setw(6) << hit.phimax <<
" outBounds, cross-check");
1850 const std::vector<const Trk::MeasurementBase*>& rots,
double seg_phimin,
1851 double seg_phimax)
const {
1852 bool hasUpdated =
false;
1859 if (ldir.z() < 0.0001)
return false;
1861 double dXdZ = ldir.x() / ldir.z();
1863 double xline = lsegPos.x();
1864 double zline = lsegPos.z();
1865 ATH_MSG_VERBOSE(
" Associated hits " << rots.size() <<
" angleXZ " << 90. * segLocDir.
angleXZ() / (M_PI_2) <<
" dXdZ " << dXdZ
1866 <<
" seg Pos (" << xline <<
" " << zline <<
") " << segLocPos);
1868 std::vector<HitInXZ> hits;
1869 hits.reserve(rots.size());
1871 unsigned int nphiHits(0);
1872 const HitInXZ* firstPhiHit{
nullptr}, *lastPhiHit{
nullptr};
1876 if (!
id.is_valid())
continue;
1878 double lxmin{0}, lxmax{0}, phimin{0}, phimax{0};
1886 lxmin = tubeEnds.
lxmin;
1887 lxmax = tubeEnds.
lxmax;
1888 phimin = tubeEnds.
phimin;
1889 phimax = tubeEnds.
phimax;
1891 lpos = gToSegment * meas->globalPosition();
1903 lxmin = lpos.x() - 0.5 * stripLength;
1904 lxmax = lpos.x() + 0.5 * stripLength;
1908 locPosition[0] = lxmin;
1910 double phi1 = globalPos.phi();
1912 locPosition[0] = lxmax;
1913 globalPos = segmentToGlobal * locPosition;
1914 double phi2 = globalPos.phi();
1915 phimin = std::min(phi1, phi2);
1916 phimax = std::max(phi1, phi2);
1928 ATH_MSG_WARNING(
"dynamic cast failed for CompetingMuonClustersOnTrack");
1934 const Amg::Vector3D segFrame_StripDir = gToSegment.linear()* detEl->stripDir(gasGap, stripNo);
1935 const Amg::Vector3D segFrame_stripPos = gToSegment * detEl->channelPos(
id);
1937 lpos = segFrame_stripPos +
1938 Amg::intersect<3>(lsegPos, ldir, segFrame_stripPos, segFrame_StripDir).value_or(0) * segFrame_StripDir;
1945 phimin = globalPos.phi();
1951 ATH_MSG_DEBUG(
" Inconsistent phi " << phimin <<
" range " << seg_phimin <<
" " << seg_phimax);
1956 hits.emplace_back(
id, isMdt, measuresPhi, lpos.x(), lpos.z(), lxmin, lxmax, phimin, phimax);
1960 firstPhiHit = &hits.back();
1962 double distPhiHits = std::abs(firstPhiHit->
z - hits.back().z);
1963 if (distPhiHits > 500.) {
1964 lastPhiHit = &hits.back();
1972 if (msgLvl(MSG::VERBOSE)) {
1973 double locExX = xline + dXdZ * (lpos.z() - zline);
1975 << std::setw(6) << (
int)lpos.z() <<
") ex pos " << std::setw(6) << (
int)locExX <<
" min "
1976 << std::setw(6) << (
int)lxmin <<
" max " << std::setw(6) << (
int)lxmax <<
" phimin " << std::setw(6)
1977 << phimin <<
" phimax " << std::setw(6) << phimax);
1978 if (lpos.x() < lxmin || lpos.x() > lxmax)
ATH_MSG_VERBOSE(
" outBounds");
1982 if (nphiHits == 1) {
1984 ATH_MSG_WARNING(
" Pointer to first phi hit not set, this should not happen! ");
1986 if (xline != firstPhiHit->
x) {
1990 xline = firstPhiHit->
x;
1991 zline = firstPhiHit->
z;
1997 double dz = ipLocPos.z() - zline;
1998 if (std::abs(dz) > 0.001) {
1999 ATH_MSG_VERBOSE(
" hit (" << xline <<
"," << zline <<
") IP (" << ipLocPos.x() <<
"," << ipLocPos.z()
2000 <<
") dXdZ " << (ipLocPos.x() - xline) / dz <<
" old " << dXdZ);
2001 dXdZ = (ipLocPos.x() - xline) / dz;
2006 }
else if (nphiHits == 2) {
2007 if (!firstPhiHit || !lastPhiHit) {
2008 ATH_MSG_WARNING(
" Pointer to one of the two phi hit not set, this should not happen! ");
2010 double dz = lastPhiHit->z - firstPhiHit->
z;
2012 xline = firstPhiHit->
x;
2013 zline = firstPhiHit->
z;
2014 if (std::abs(dz) > 300.) {
2015 double dx = lastPhiHit->x - firstPhiHit->
x;
2028 double segX = xline - dXdZ * zline;
2034 ATH_MSG_DEBUG(
"still several out of bounds hits after rotation: posx(" << segX <<
") dXdZ " << dXdZ
2035 <<
" keeping old result ");
2039 double alphaYZ = segLocDir.
angleYZ();
2040 double alphaXZ = std::atan2(1, dXdZ);
2059 double tubeLen = (lropos - lhvpos).
mag();
2060 double activeTubeLen =
2062 double scaleFactor = activeTubeLen / tubeLen;
2063 lropos[0] = scaleFactor * lropos.x();
2064 lhvpos[0] = scaleFactor * lhvpos.x();
2066 tubeEnds.
lxmin = std::min(lropos.x(), lhvpos.x());
2067 tubeEnds.
lxmax = std::max(lropos.x(), lhvpos.x());
2071 const double phiRO = ropos.phi();
2072 const double phiHV = hvpos.phi();
2073 tubeEnds.
phimin = std::min(phiRO, phiHV);
2074 tubeEnds.
phimax = std::max(phiRO, phiHV);
2080 if (phiminRef * phimaxRef < 0.) {
2081 if (phiminRef < -1.1) {
2082 if (phiminRef > phiminNew) phiminRef = phiminNew;
2083 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2085 if (phiminRef < phiminNew) phiminRef = phiminNew;
2086 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2090 if (phiminRef < 0.) {
2091 if (phiminRef < phiminNew) phiminRef = phiminNew;
2092 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2094 if (phiminRef > phiminNew) phiminRef = phiminNew;
2095 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2105 double offset = 0.05;
2106 if (phimin * phimax < 0.) {
2109 if (
phi < phimin - offset) phiOk =
false;
2111 if (
phi > phimin + offset) phiOk =
false;
2115 if (
phi < phimax - offset) phiOk =
false;
2117 if (
phi > phimax + offset) phiOk =
false;
2127 bool isCurvedSegment)
const {
2139 double dx = std::sin(gdirs.theta()) * std::cos(gdirs.phi());
2140 double dy = std::sin(gdirs.theta()) * std::sin(gdirs.phi());
2141 double dz = std::cos(gdirs.theta());
2145 double dxo = std::sin(gdiro.theta()) * std::cos(gdiro.phi());
2146 double dyo = std::sin(gdiro.theta()) * std::sin(gdiro.phi());
2147 double dzo = std::cos(gdiro.theta());
2155 double a0 = dx * std::sin(roaddir.phi()) - dy * std::cos(roaddir.phi());
2156 double b0 = dxo * std::sin(roaddir.phi()) - dyo * std::cos(roaddir.phi());
2157 if (b0 < 1e-8 && b0 > 0) b0 = 1e-8;
2158 if (b0 > -1e-8 && b0 < 0) b0 = -1e-8;
2159 double dxn = dx -
a0 * dxo / b0;
2160 double dyn = dy -
a0 * dyo / b0;
2161 double dzn = dz -
a0 * dzo / b0;
2162 double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn);
2166 if (dxn * roaddir.x() + dyn * roaddir.y() + dzn * roaddir.z() < 0.) { norm = -norm; }
2168 if (dxn * roaddir.x() + dyn * roaddir.y() < 0.) { norm = -norm; }
2171 if (isCurvedSegment) norm = norm / 2.;
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
double charge(const T &p)
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
static Timeout & instance()
Get reference to Timeout singleton.
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
This is a "hash" representation of an Identifier.
unsigned int nMDTinStation() const
How many MDT chambers are in the station.
double getActiveTubeLength(const int tubeLayer, const int tube) const
Amg::Vector3D ROPos(const int tubelayer, const int tube) const
int getNLayers() const
Returns the number of tube layers inside the multilayer.
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
virtual const Amg::Vector3D & center(const Identifier &) const override final
Return the center of the surface associated with this identifier In the case of silicon it returns th...
virtual const Amg::Vector3D & center() const override
Return the center of the element.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
virtual Amg::Transform3D AmdbLRSToGlobalTransform() const
virtual Amg::Transform3D GlobalToAmdbLRSTransform() const
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
A TgcReadoutElement corresponds to a single TGC chamber; therefore typically a TGC station contains s...
Amg::Vector3D localSpacePoint(const Identifier &stripId, const Amg::Vector3D &etaHitPos, const Amg::Vector3D &phiHitPos) const
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
const MuonClusterOnTrack & rioOnTrack(unsigned int) const
returns the RIO_OnTrack (also known as ROT) objects depending on the integer
Gaudi::Property< bool > m_doSpacePoints
void find(const std::vector< const Trk::RIO_OnTrack * > &rios, Trk::SegmentCollection *segColl=nullptr) const
find segments starting from a list of RIO_OnTrack objects, implementation of IMuonSegmentMaker interf...
std::unique_ptr< MuonSegment > createSegment(const EventContext &ctx, TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Vector3D &roadpos, const Amg::Vector3D &roaddir2, const std::vector< const MdtDriftCircleOnTrack * > &mdts, bool hasPhiMeasurements, segmentCreationInfo &sInfo, double beta=1.) const
bool errorScalingRegion(const Identifier &id) const
apply error scaling for low mometum tracks
ClusterVecPair create1DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
std::map< Identifier, EtaPhiHitsPair > IdHitMap
Gaudi::Property< bool > m_addUnassociatedPhiHits
Gaudi::Property< bool > m_updatePhiUsingPhiHits
Gaudi::Property< bool > m_recoverBadRpcCabling
ToolHandle< IDCSLFitProvider > m_dcslFitProvider
Gaudi::Property< bool > m_doGeometry
Amg::Vector3D updateDirection(double linephi, const Trk::PlaneSurface &surf, const Amg::Vector3D &roaddir, bool isCurvedSegment) const
update the global direction, keeping the phi of the input road direction but using the local angle YZ
Gaudi::Property< double > m_sinAngleCut
Gaudi::Property< bool > m_removeDeltas
ToolHandle< IMuonClusterOnTrackCreator > m_clusterCreator
Gaudi::Property< bool > m_createCompetingROTsEta
ToolHandle< IMuonSegmentSelectionTool > m_segmentSelectionTool
std::map< Identifier, IdHitMap > ChIdHitMap
TrkDriftCircleMath::MdtChamberGeometry createChamberGeometry(const Identifier &chid, const Amg::Transform3D &gToStation) const
Gaudi::Property< bool > m_doTimeOutChecks
static double distanceToSegment(const TrkDriftCircleMath::Segment &segment, const Amg::Vector3D &hitPos, const Amg::Transform3D &gToStation)
Gaudi::Property< bool > m_outputFittedT0
const MdtDriftCircleOnTrack * findFirstRotInChamberWithMostHits(const std::vector< const MdtDriftCircleOnTrack * > &mdts) const
Gaudi::Property< double > m_preciseErrorScale
Gaudi::Property< bool > m_reject1DTgcSpacePoints
ToolHandle< IMuonSegmentFittingTool > m_segmentFitter
PublicToolHandle< MuonEDMPrinterTool > m_printer
virtual StatusCode initialize()
TrkDriftCircleMath::CLVec createClusterVec(const Identifier &chid, ClusterVec &spVec, const Amg::Transform3D &gToStation) const
Cluster2D createTgcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Gaudi::Property< bool > m_curvedErrorScaling
Gaudi::Property< bool > m_redo2DFit
Gaudi::Property< bool > m_allMdtHoles
Gaudi::Property< bool > m_refitParameters
std::vector< Cluster2D > ClusterVec
bool updateSegmentPhi(const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, Amg::Vector2D &segLocPos, Trk::LocalDirection &segLocDir, Trk::PlaneSurface &surf, const std::vector< const Trk::MeasurementBase * > &rots, double phimin, double phimax) const
TubeEnds localTubeEnds(const MdtDriftCircleOnTrack &mdt, const Amg::Transform3D &gToSegment, const Amg::Transform3D &segmentToG) const
calculate positions of tube ends
static void updatePhiRanges(double phiminNew, double phimaxNew, double &phiminRef, double &phimaxRef)
update phi ranges
SG::ReadHandleKey< Muon::MdtPrepDataContainer > m_mdtKey
ClusterVecPair create2DClusters(const std::vector< const MuonClusterOnTrack * > &clusters) const
SG::ReadCondHandleKey< Muon::MuonIntersectGeoData > m_chamberGeoKey
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_DetectorManagerKey
pointers to IdHelpers
bool checkBoundsInXZ(double xline, double zline, double dXdZ, const std::vector< HitInXZ > &hits) const
check whether all hits are in bounds in the XZ plane
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compClusterCreator
void associateMDTsToSegment(const Amg::Vector3D &gdir, TrkDriftCircleMath::Segment &segment, const TrkDriftCircleMath::ChamberGeometry *multiGeo, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec, double beta=1.) const
double errorScaleFactor(const Identifier &id, double curvature, bool hasPhiMeasurements) const
calculate error scaling factor
Cluster2D createRpcSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const std::vector< const MuonClusterOnTrack * > &phiHits) const
Gaudi::Property< bool > m_createCompetingROTsPhi
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreator
Cluster2D createSpacePoint(const Identifier &gasGapId, const MuonClusterOnTrack *etaHit, const MuonClusterOnTrack *phiHit) const
Gaudi::Property< double > m_maxAssociateClusterDistance
std::pair< ClusterVec, ClusterVec > ClusterVecPair
ClusterVecPair createSpacePoints(const ChIdHitMap &chIdHitMap) const
const MdtPrepData * findMdt(const EventContext &ctx, const Identifier &id) const
Gaudi::Property< bool > m_usePreciseError
std::pair< std::pair< int, int >, bool > associateClustersToSegment(const TrkDriftCircleMath::Segment &segment, const Identifier &chid, const Amg::Transform3D &gToStation, ClusterVecPair &spVecs, double phimin, double phimax, std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
ToolHandle< IMdtSegmentFinder > m_segmentFinder
static DataVector< const Trk::MeasurementBase > createROTVec(std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec)
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreatorT0
Gaudi::Property< bool > m_assumePointingPhi
static std::pair< double, double > residualAndPullWithSegment(const TrkDriftCircleMath::Segment &segment, const Cluster2D &spacePoint, const Amg::Transform3D &gToStation)
bool checkPhiConsistency(double phi, double phimin, double phimax) const
check whether phi is consistent with segment phi
std::vector< Identifier > calculateHoles(const EventContext &ctx, Identifier chid, const Amg::Vector3D &gpos, const Amg::Vector3D &gdir, bool hasMeasuredCoordinate, std::set< Identifier > &deltaVec, std::set< Identifier > &outoftimeVec, const std::vector< std::pair< double, std::unique_ptr< const Trk::MeasurementBase > > > &rioDistVec) const
TrkDriftCircleMath::DCVec createDCVec(const std::vector< const MdtDriftCircleOnTrack * > &mdts, double errorScale, std::set< Identifier > &chamberSet, double &phimin, double &phimax, TrkDriftCircleMath::DCStatistics &dcStatistics, const Amg::Transform3D &gToStation, const Amg::Transform3D &amdbToGlobal) const
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
virtual const Amg::Vector3D & globalPosition() const override final
Returns the global Position.
double driftRadius() const
Returns the value of the drift radius.
double driftTime() const
Returns the value of the drift time used to obtain the drift radius.
virtual const Trk::StraightLineSurface & associatedSurface() const override final
Returns the surface on which this measurement was taken.
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
Class to represent measurements from the Monitored Drift Tubes.
virtual const MuonGM::MdtReadoutElement * detectorElement() const override
Returns the detector element corresponding to this PRD.
virtual const Amg::Vector3D & globalPosition() const
Returns the global position of the CENTER of the drift tube (i.e.
Base class for Muon cluster RIO_OnTracks.
virtual const MuonGM::MuonClusterReadoutElement * detectorElement() const override=0
Returns the detector element, associated with the PRD of this class.
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
virtual const Amg::Vector3D & globalPosition() const override
Returns global position.
This is the common muon segment quality object.
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
virtual LocVec2D tubePosition(unsigned int ml, unsigned int lay, unsigned int tube) const =0
virtual unsigned int nlay() const =0
class representing a cluster meaurement
class representing a drift circle meaurement on segment
@ OutOfTime
delta electron
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
const HitSelection selectHitsOnTrack(const DCOnTrackVec &dcs) const
This class offers no functionality, but to define a standard device for the maker to transfer to the ...
This class represents a drift time measurement.
@ InTime
drift time too small to be compatible with drift spectrum
Implementation of 2 dimensional vector class.
double y() const
Returns the y coordinate of the vector.
double x() const
Returns the x coordinate of the vector.
void print(MsgStream &msg) const override
double residual(const LocVec2D &pos) const
class to calculate residual of a hit with a segment and calculate the local track errors
double trackError2(const DriftCircle &dc) const
calculate the track error at the position of a drift circle
TrkDriftCircleMath::Road - encodes the road given to the segment finder in station coordinates.
void hitsOnTrack(unsigned int hitsOnTrack)
bool hasCurvatureParameters() const
const Line & line() const
const CLVec & clusters() const
const DCOnTrackVec & dcs() const
double deltaAlpha() const
unsigned int ndof() const
represents the three-dimensional global direction with respect to a planar surface frame.
double angleXZ() const
access method for angle of local XZ projection
double angleYZ() const
access method for angle of local YZ projection
This class is the pure abstract base class for all fittable tracking measurements.
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
std::unique_ptr< MeasurementBase > uniqueClone() const
NVI Clone giving up unique pointer.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
void localToGlobalDirection(const Trk::LocalDirection &locdir, Amg::Vector3D &globdir) const
This method transforms a local direction wrt the plane to a global direction.
const Amg::Vector2D & localPosition() const
return the local position reference
const Amg::MatrixX & localCovariance() const
return const ref to the error matrix
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
virtual const Surface & associatedSurface() const override=0
returns the surface for the local to global transformation
Identifier identify() const
return the identifier -extends MeasurementBase
std::unique_ptr< RIO_OnTrack > uniqueClone() const
NVI clone returning unique_ptr.
@ DCMathSegmentMakerCurved
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for StraightLineSurface: GlobalToLocal method without dynamic memory allocation This method...
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Encapsulates the information required by the find() method of the muon segment makers.
const Amg::Vector3D & globalPosition() const
Get the global position of the road.
double deltaEta() const
Get the width of the road in the eta direction.
const Amg::Vector3D & globalDirection() const
Get the global direction of the road.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
PhiIndex
enum to classify the different phi layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
ChIndex
enum to classify the different chamber layers in the muon spectrometer
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
MuonPrepDataCollection< MdtPrepData > MdtPrepDataCollection
@ OWN_ELEMENTS
this data object owns its elements
std::vector< Cluster > CLVec
std::vector< Segment > SegVec
std::vector< DriftCircle > DCVec
std::vector< DCOnTrack > DCOnTrackVec
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
DataVector< Trk::Segment > SegmentCollection
@ loc2
generic first and second local coordinate
ParametersBase< TrackParametersDim, Charged > TrackParameters
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Identifier identify() const
const MuonClusterOnTrack * phiHit
std::vector< const MuonClusterOnTrack * > phiHits
Amg::Transform3D globalTrans
const TrkDriftCircleMath::ChamberGeometry * geom
Amg::Transform3D amdbTrans
IdDataVec(const Identifier &i)
std::vector< Entry > EntryVec
Function object to sort pairs containing a double and a pointer to a MuonClusterOnTrack.
bool operator()(const std::pair< double, DCMathSegmentMaker::Cluster2D > &d1, const std::pair< double, DCMathSegmentMaker::Cluster2D > &d2)
bool operator()(const IdDataVec< T > &d1, const IdDataVec< T > &d2)