50 double cot(
double x) {
52 constexpr double dX = std::numeric_limits<float>::epsilon();
53 if (std::abs(
x) < dX || std::abs(
x -
M_PI) < dX)
return std::numeric_limits<float>::max();
55 return std::tan(M_PI_2 -
x);
57 template <
typename T>
constexpr T absmax(
const T&
a,
const T& b) {
58 return std::abs(
a) > std::abs(b) ?
a :
b;}
82 return StatusCode::SUCCESS;
86 const std::vector<const MdtDriftCircleOnTrack*>& mdts,
87 const std::vector<const MuonClusterOnTrack*>& clusters,
bool hasPhiMeasurements,
89 const EventContext& ctx = Gaudi::Hive::currentContext();
95 ATH_MSG_DEBUG(
"In find, passed " << mdts.size() <<
" MDTs & "<<clusters.size()<<
" clusters");
97 if (mdts.size() < 3)
return;
101 if (!firstRot) {
return; }
125 double chamber_angleYZ = std::atan2(dirCh.z(), dirCh.y());
128 double dotprod = globalDirCh.perp() * std::sin(roaddir2.theta()) + globalDirCh.z() * std::cos(roaddir2.theta());
129 if (dotprod < 0) roaddir2 = -roaddir2;
134 double road_angleXZ = std::atan2(d.z(), d.x());
135 double road_angleYZ = std::atan2(d.z(), d.y());
137 if (!hasPhiMeasurements) road_angleXZ =
M_PI;
139 << isEndcap <<
" central phi " << detEl->
center().phi() <<
" r " << detEl->
center().perp()
140 <<
" z " << detEl->
center().z());
155 if (msgLvl(MSG::VERBOSE)) {
156 std::stringstream sstr{};
159 ATH_MSG_VERBOSE(
" adding mdts " << mdts.size()<<std::endl<<sstr.str());
163 std::set<Identifier> chamberSet;
164 double phimin{-9999}, phimax{9999};
169 std::shared_ptr<const TrkDriftCircleMath::ChamberGeometry> multiGeo;
171 ATH_MSG_VERBOSE(
" using chamber geometry with #chambers " << chamberSet.size());
173 std::vector<TrkDriftCircleMath::MdtChamberGeometry> geos{};
176 geos.reserve(chamberSet.size());
182 multiGeo = std::make_unique<TrkDriftCircleMath::MdtMultiChamberGeometry>(geos);
188 if (sinAngleCut > 0)
angle = sinAngleCut;
194 if (msgLvl(MSG::VERBOSE)) {
195 std::stringstream sstr{};
196 unsigned int seg_n{0};
198 constexpr double toDeg = 1./Gaudi::Units::degree;
199 sstr<<
"Segment number "<<seg_n<<
" is at ("<<seg.line().x0()<<
","<<seg.line().y0()<<
") pointing to "<<seg.line().phi()*toDeg<<
" chi2: "<<
200 (seg.chi2()/seg.ndof())<<
"("<<seg.ndof()<<
")"<<std::endl;
201 sstr<<
"Mdt measurements: "<<seg.dcs().size()<<std::endl;
203 sstr<<
" **** "<<
m_printer->print(*mdt_meas.rot());
204 sstr<<
" ("<<mdt_meas.state()<<
")"<<std::endl;
206 sstr<<
"Cluster measurements "<<seg.clusters().size()<<std::endl;
208 sstr<<
" ---- "<<
m_printer->print(*clus.rot())<<std::endl;
213 ATH_MSG_VERBOSE(
"Found " << segs.size() <<
" segments "<<std::endl<<sstr.str());
217 if (segs.empty()) {
return; }
220 segmentCreationInfo sInfo(spVecs, multiGeo.get(), gToStation, amdbToGlobal, phimin, phimax);
222 std::unique_ptr<MuonSegment> segment =
createSegment(ctx, seg, chid, roadpos, roaddir2, mdts, hasPhiMeasurements, sInfo, beta);
223 if (segment) segColl->
push_back(segment.release());
230 const std::vector<const MdtDriftCircleOnTrack*>& mdts,
bool hasPhiMeasurements,
236 static constexpr std::array<ChIndex ,4> statWithField{ChIndex::BIL, ChIndex::BML, ChIndex::BMS, ChIndex::BOL};
238 std::ranges::find(statWithField,
chIndex) != statWithField.end();
246 ATH_MSG_DEBUG(
"New segment: chi2 " << segment.
chi2() <<
" ndof " << segment.
ndof() <<
" line " << line.position().x() <<
","
247 << line.position().y() <<
" phi " << line.phi() <<
" associated clusters "
257 if (hasPhiMeasurements) {
261 double cphi = lroaddir.x();
265 lxroad = lroadpos.x() + (-lroadpos.y() + line.position().x()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
268 lxroad = lroadpos.x() + (-lroadpos.z() + line.position().y()) * cphi / absmax(sphi, std::numeric_limits<double>::min());
271 double shortestTubeLen = 1e9;
280 if (tubelen < shortestTubeLen) shortestTubeLen = tubelen;
283 if (std::abs(lxroad) > shortestTubeLen) {
284 ATH_MSG_DEBUG(
"coordinates far outside chamber! using global position of first hit ");
285 if (lxroad < 0.) shortestTubeLen *= -1.;
286 lxroad = shortestTubeLen;
289 lxroad = (sInfo.
globalTrans * mdts[0]->prepRawData()->detectorElement()->surface(mdts[0]->identify()).center()).x();
293 Amg::Vector3D lpos(lxroad, line.position().x(), line.position().y());
300 surfaceTransform.pretranslate(gpos);
301 double surfDim = 500.;
302 std::unique_ptr<Trk::PlaneSurface> surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
306 double linephi = line.phi();
313 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>> > rioDistVec;
316 std::set<Identifier> deltaVec;
317 std::set<Identifier> outoftimeVec;
320 std::vector<std::pair<double, std::unique_ptr<const Trk::MeasurementBase>>> garbage_collector;
331 std::abs(segment.
line().
x0() - result.line().x0()) > 0.01 ||
332 std::abs(segment.
line().
y0() - result.line().y0()) > 0.01) {
334 linephi = result.line().phi();
335 lpos[1] = result.line().position().x();
336 lpos[2] = result.line().position().y();
341 surfaceTransform.pretranslate(gpos);
342 surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
352 surf->globalToLocalDirection(gdir, segLocDir);
362 if (std::min(std::abs(diff_phi), std::abs( std::abs(diff_phi) -
M_PI)) > 1.e-3 ||
363 std::min(std::abs(diff_prec), std::abs(std::abs(diff_prec) -
M_PI)) > 1.e-3) {
364 ATH_MSG_WARNING(
" ALARM updated angles wrong: diff phi " << diff_phi <<
" prec " << diff_prec <<
" phi rdir " << roaddir2.phi()
365 <<
" gdir " << gdir.phi() <<
" lphi " << linephi <<
" seg "
370 std::pair<std::pair<int, int>,
bool> netaPhiHits =
373 if (rioDistVec.empty()){
379 auto meas_for_fit = [&rioDistVec] () {
380 std::vector<const Trk::MeasurementBase*> out{};
381 out.reserve(rioDistVec.size());
383 for (
const std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& ele : rioDistVec) out.push_back(ele.second.get());
388 double dlocx{1000.}, dangleXZ{1000.}, qoverp{-99999.}, dqoverp{-99999.};
389 bool hasMeasuredCoordinate =
false;
391 ATH_MSG_DEBUG(
" distance between first and last phi hit sufficient to perform 4D fit: phi " << gdir.phi() <<
" theta "
394 std::unique_ptr<Trk::Track> track{
m_segmentFitter->fit(gpos, gdir, *surf, meas_for_fit())};
397 if (isCurvedSegment && track->perigeeParameters() && track->perigeeParameters()->covariance()) {
398 qoverp = track->perigeeParameters()->parameters()[
Trk::qOverP];
401 hasMeasuredCoordinate =
true;
404 updatedCov.setZero();
405 m_segmentFitter->updateSegmentParameters(*track, *surf, segLocPos, segLocDir, updatedCov);
414 surf->localToGlobal(segLocPos, gdir, gpos);
415 surf->localToGlobalDirection(segLocDir, gdir);
417 if (track->measurementsOnTrack() && rioDistVec.size() != track->measurementsOnTrack()->size()) {
418 if (track->measurementsOnTrack()->empty()) {
422 ATH_MSG_DEBUG(
" ROT vector size changed after fit, updating ");
423 garbage_collector = std::move(rioDistVec);
424 rioDistVec.reserve(track->measurementsOnTrack()->size());
429 if (!firstPars) firstPars = pars;
435 double dist = (pars->position() - firstPars->
position()).dot(firstPars->
momentum().unit());
436 rioDistVec.emplace_back(dist, meas->
uniqueClone());
441 netaPhiHits.second =
false;
449 surf->localToGlobal(segLocPos, gpos, gpos);
450 surf->localToGlobalDirection(segLocDir, gdir);
451 hasMeasuredCoordinate =
true;
457 if (msgLvl(MSG::DEBUG)) {
458 std::vector<const Trk::MeasurementBase*> debug_meas = meas_for_fit();
459 ATH_MSG_DEBUG(
" number of hits " << debug_meas.size() <<
" of which trigger " << netaPhiHits.first.first <<
" eta and "
460 << netaPhiHits.first.second <<
" phi ");
468 <<
" radius " << std::setw(6) << mdt->
driftRadius() <<
" time " << std::setw(6) << mdt->
driftTime());
481 std::vector<Identifier> holeVec =
calculateHoles(ctx, chid, gpos, gdir, hasMeasuredCoordinate, deltaVec, outoftimeVec, rioDistVec);
484 if (!outoftimeVec.empty()) holeVec.insert(holeVec.end(), std::make_move_iterator(outoftimeVec.begin()),
485 std::make_move_iterator(outoftimeVec.end()));
494 ATH_MSG_DEBUG(
" Fitted T0 " << result.t0Shift()<<
" is valid "<<result.hasT0Shift());
497 bool hasFittedT0 =
false;
498 double fittedT0{0}, errorFittedT0{1.};
503 errorFittedT0 = segment.
t0Error();
504 }
else if (dcslFitter && result.hasT0Shift()) {
505 fittedT0 = result.t0Shift();
506 errorFittedT0 = result.t0Error();
513 std::unique_ptr<MuonSegment> msegment;
514 if (isCurvedSegment) {
515 if (qoverp == -99999.) {
516 double charge = gpos.z() * std::tan(gdir.theta());
519 constexpr double BILALPHA(28.4366), BMLALPHA(62.8267), BMSALPHA(53.1259), BOLALPHA(29.7554);
522 dqoverp = M_SQRT2 * segment.
dtheta() / BILALPHA;
523 }
else if (
chIndex == ChIndex::BML) {
525 dqoverp = M_SQRT2 * segment.
dtheta() / BMLALPHA;
526 }
else if (
chIndex == ChIndex::BMS) {
528 dqoverp = M_SQRT2 * segment.
dtheta() / BMSALPHA;
529 }
else if (
chIndex == ChIndex::BOL) {
531 dqoverp = M_SQRT2 * segment.
dtheta() / BOLALPHA;
535 covMatrix.setIdentity();
536 covMatrix(0, 0) = dlocx * dlocx;
537 covMatrix(1, 1) = segment.
dy0() * segment.
dy0();
538 covMatrix(2, 2) = dangleXZ * dangleXZ;
540 covMatrix(4, 4) = dqoverp * dqoverp;
542 std::vector<Trk::DefinedParameter> defPars;
545 defPars.emplace_back(gdir.phi(),
Trk::phi);
546 defPars.emplace_back(gdir.theta(),
Trk::theta);
549 msegment = std::make_unique<MuonSegment>(
550 std::move(segLocPar),
551 std::move(covMatrix),
559 covMatrix.setIdentity();
560 covMatrix(0, 0) = dlocx * dlocx;
561 covMatrix(1, 1) = segment.
dy0() * segment.
dy0();
562 covMatrix(2, 2) = dangleXZ * dangleXZ;
565 std::make_unique<MuonSegment>(segLocPos,
567 std::move(covMatrix),
574 if (hasFittedT0) msegment->setT0Error(fittedT0, errorFittedT0);
579 if (msgLvl(MSG::DEBUG)) {
585 if (segmentQuality < 0) {
return nullptr; }
590 std::vector<const MdtDriftCircleOnTrack*> mdts;
591 std::vector<const MuonClusterOnTrack*> clusters;
597 if (!mdt) {
ATH_MSG_WARNING(
"failed dynamic_cast, not a MDT but hit has MDT id!!!"); }
601 if (!clus) {
ATH_MSG_WARNING(
"failed dynamic_cast, not a cluster but hit has RPC/TGC id!!!"); }
602 clusters.push_back(clus);
605 find(mdts, clusters, segColl);
610 if (mdts.empty())
return;
615 bool hasPhiMeasurements =
false;
618 find(gpos, gdir, mdts, clusters, hasPhiMeasurements, segColl);
622 const std::vector<const Trk::RIO_OnTrack*>& rios2)
const {
623 std::vector<const Trk::RIO_OnTrack*> rios = rios1;
624 rios.insert(rios.end(), rios2.begin(), rios2.end());
630 bool hasPhiMeasurements,
double momentum)
const {
632 std::vector<const MdtDriftCircleOnTrack*> all_mdts;
633 for (
const std::vector<const MdtDriftCircleOnTrack*>& circle_vec : mdts) { std::copy(circle_vec.begin(), circle_vec.end(), std::back_inserter(all_mdts)); }
636 std::vector<const MuonClusterOnTrack*> all_clus;
637 for (
const std::vector<const MuonClusterOnTrack*>& clus_vec : clusters) { std::copy(clus_vec.begin(), clus_vec.end(), std::back_inserter(all_clus)); }
641 find(gpos, gdir, all_mdts, all_clus, hasPhiMeasurements, segColl, momentum, road.
deltaEta());
650 double scaleMax = 5.;
652 scale = std::min(scaleMax, 1. + curvature / 10000);
653 ATH_MSG_DEBUG(
" rescaled errors " << scale <<
" curvature " << curvature);
658 if (!hasPhiMeasurements) {
659 double phiScale = 1.;
661 int stRegion =
m_idHelperSvc->mdtIdHelper().stationRegion(
id);
664 else if (stRegion == 1)
666 else if (stRegion == 2)
670 scale = std::sqrt(scale*scale + phiScale*phiScale);
671 ATH_MSG_DEBUG(
" rescaled error for missing phi road " << scale);
687 if (
stName[1] ==
'I')
return true;
697 if (clusters.empty())
return {};
703 clVec.reserve(clusters.size());
711 if (phiVec.back().corrupt()) phiVec.pop_back();
714 if (clVec.back().corrupt()) clVec.pop_back();
723 if (clusters.empty())
return {};
734 gasGapHitMap[chId][gasGapId].first.push_back(clus);
736 gasGapHitMap[chId][gasGapId].second.push_back(clus);
745 spacePoints.reserve(20);
748 for (
const auto& [
id, gasGapHits] : chIdHitMap) {
751 std::copy(std::make_move_iterator(cls.first.begin()),
752 std::make_move_iterator(cls.first.end()), std::back_inserter(spacePoints));
753 std::copy(std::make_move_iterator(cls.second.begin()),
754 std::make_move_iterator(cls.second.end()), std::back_inserter(phiVec));
757 return std::make_pair(std::move(spacePoints), std::move(phiVec));
762 bool isEndcap =
m_idHelperSvc->isEndcap((*(gasGapHitMap.begin())).first);
764 ATH_MSG_VERBOSE(
" creating Space points for " << gasGapHitMap.size() <<
" gas gaps ");
766 for (
const auto& [gasGapId, etaPhiHits] : gasGapHitMap) {
768 std::vector<bool> flagPhihit(etaPhiHits.second.size(), 0);
774 << etaPhiHits.second.size());
778 if (etaHit->
identify() == prevEtaId)
continue;
785 bool foundSP =
false;
791 if (phiHit->
identify() == prevPhiId)
continue;
797 if (
sp.corrupt())
continue;
798 spacePoints.push_back(std::move(
sp));
801 flagPhihit[phi_idx] =
true;
807 if (
sp.corrupt())
continue;
808 spacePoints.push_back(std::move(
sp));
812 if (
sp.corrupt())
continue;
814 flagPhihit = std::vector<bool>(etaPhiHits.second.size(), 1);
815 spacePoints.push_back(std::move(
sp));
821 for (
unsigned int i = 0; i < flagPhihit.size(); ++i) {
822 if (flagPhihit[i])
continue;
825 if (etaPhiHits.second[i]->identify() == prevPhiId)
continue;
826 prevPhiId = etaPhiHits.second[i]->identify();
829 if (
sp.corrupt())
continue;
830 phiVec.push_back(std::move(
sp));
832 }
else if (etaPhiHits.first.empty() && !etaPhiHits.second.empty()) {
835 if (
sp.corrupt())
continue;
836 phiVec.push_back(std::move(
sp));
840 ATH_MSG_VERBOSE(
" Creating space points, number of gas-gaps " << gasGapHitMap.size() <<
" space points " << spacePoints.size());
842 return std::make_pair(std::move(spacePoints), std::move(phiVec));
848 double error{1.}, lpx{0.}, lpy{0.};
858 }
else if (!phiHit) {
861 }
else if (etaHit && phiHit) {
865 std::vector<const MuonClusterOnTrack*> phiVec{phiHit};
870 if (std::abs(
error) < 0.001) {
880 double error{1.}, lpx{0.}, lpy{0.};
886 }
else if (!phiHit) {
889 }
else if (etaHit && phiHit) {
898 lpx = lSpacePoint.x();
899 lpy = lSpacePoint.y();
901 if (
error <= std::numeric_limits<double>::epsilon()) {
910 if (std::abs(
error) < 0.001) {
919 const std::vector<const MuonClusterOnTrack*>& phiHits)
const {
921 std::vector<const MuonClusterOnTrack*> cleanPhihits;
922 cleanPhihits.reserve(phiHits.size());
924 double error{1.}, lpx{0.}, lpy{0.};
927 lpx = phiHits.front()->localParameters()[
Trk::locX];
933 if (clus->identify() == prevId)
continue;
934 prevId = clus->identify();
935 cleanPhihits.push_back(clus);
937 }
else if (phiHits.empty()) {
940 }
else if (etaHit && !phiHits.empty()) {
947 double minPos{1e9}, maxPos{-1e9};
953 if (phiHit->identify() == prevId)
continue;
954 prevId = phiHit->identify();
960 minPos = std::min(minPos, lpy);
961 maxPos = std::max(maxPos, lpy);
963 cleanPhihits.push_back(phiHit);
966 if (cleanPhihits.size() > 1)
967 ATH_MSG_DEBUG(
" multiple phi hits: nhits " << cleanPhihits.size() <<
" cl width " << maxPos - minPos);
972 if (std::abs(
error) < 0.001) {
983 const int chPhi =
m_idHelperSvc->mdtIdHelper().stationPhi(chid);
987 cls.reserve(spVec.size());
1016 cls.emplace_back(lp, clust.error, clid, meas,
index);
1022 std::set<Identifier>& chamberSet,
double& phimin,
double& phimax,
1026 dcs.reserve(mdts.size());
1028 bool firstMdt =
true;
1036 Amg::Vector3D locPos = gToStation * rot->prepRawData()->globalPosition();
1039 double r = rot->localParameters()[
Trk::locR];
1047 double preciseError = dr;
1054 phimin = tubeEnds.
phimin;
1055 phimax = tubeEnds.
phimax;
1062 << rot->driftTime() <<
" r " <<
r <<
" dr " << dr <<
" phi range " << tubeEnds.
phimin <<
" "
1063 << tubeEnds.
phimax<<
" precise error "<<preciseError);
1064 dcs.push_back(std::move(dc));
1066 chamberSet.insert(elId);
1068 ++dcStatistics[rot->prepRawData()->detectorElement()];
1099 ATH_MSG_ERROR(
"Null pointer to the read MuonDetectorManager conditions object");
1115 firstTubeMl1 = gToStation * (detEl2->
surface(firstIdml1).center());
1125 firstTubeMl0 = gToStation * (detEl1->
surface(firstIdml0).center());
1138 double tubeDist = (secondTubeMl0 - firstTubeMl0).
y();
1139 double tubeStage = (firstTubeMl0lay1 - firstTubeMl0).
y();
1140 double layDist = (firstTubeMl0lay1 - firstTubeMl0).
z();
1142 TrkDriftCircleMath::MdtChamberGeometry mdtgeo(chid,
m_idHelperSvc.get(), nml, nlay, ntube1, ntube2, firstTube0, firstTube1, tubeDist, tubeStage,
1145 if (msgLvl(MSG::VERBOSE)) mdtgeo.
print(msgStream());
1153 std::set<Identifier>& deltaVec, std::set<Identifier>& outoftimeVec,
1154 std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec,
double beta)
const {
1163 double ml2phi = line.phi() - segment.
deltaAlpha();
1168 double chamberMidPtY = (ml1LocPos.
y() + ml2LocPos.
y()) / 2.0;
1174 toLineml2 = tmptoLine;
1202 posAlong[1] = pointOnLineAMDB.
x();
1203 posAlong[2] = pointOnLineAMDB.
y();
1210 ATH_MSG_WARNING(
" dynamic cast to StraightLineSurface failed for mdt!!! ");
1221 std::unique_ptr<MdtDriftCircleOnTrack> nonconstDC;
1225 nonconstDC.reset(
m_mdtCreator->createRIO_OnTrack(*riodc->
prepRawData(), mdtGP, &gdir, 0.,
nullptr, beta, 0.));
1226 if (hasT0)
ATH_MSG_WARNING(
"Attempted to change t0 without a properly configured MDT creator tool. ");
1240 dcit.driftState(), dcit.id(),
1243 dcit = std::move(new_dc_on_track);
1246 if (msgLvl(MSG::VERBOSE)) {
1247 double shift = riodc->
driftTime() - nonconstDC->driftTime();
1248 ATH_MSG_VERBOSE(
" t0 shift " << segment.
t0Shift() <<
" from hit " << shift <<
" recal " << nonconstDC->driftRadius()
1249 <<
" t " << nonconstDC->driftTime() <<
" from fit " << dcit.r() <<
" old "
1251 if (std::abs(std::abs(nonconstDC->driftRadius()) - std::abs(dcit.r())) > 0.1 && nonconstDC->driftRadius() < 19. &&
1252 nonconstDC->driftRadius() > 1.) {
1258 double dist = pointOnHit.
x();
1259 rioDistVec.emplace_back(dist, std::move(nonconstDC));
1279 bool operator()(
const std::pair<double, DCMathSegmentMaker::Cluster2D>& d1,
1280 const std::pair<double, DCMathSegmentMaker::Cluster2D>& d2) {
1281 return std::abs(d1.first) < std::abs(d2.first);
1287 double phimin,
double phimax, std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec)
const {
1290 typedef std::vector<ChamberData> ChamberDataVec;
1291 ChamberDataVec chamberDataVec;
1296 std::pair<std::pair<int, int>,
bool> netaPhiHits(std::make_pair(0, 0),
false);
1297 if (segment.
clusters().empty())
return netaPhiHits;
1299 std::vector<const Trk::MeasurementBase*> phiHits;
1305 std::set<Identifier> detElOnSegments;
1306 std::set<MuonStationIndex::PhiIndex> phiIndices;
1308 ATH_MSG_DEBUG(
" Associating clusters: " << segment.
clusters().size() <<
" number of space points " << spVecs.first.size());
1313 const Cluster2D& spacePoint = spVecs.first[clust.index()];
1318 ATH_MSG_DEBUG(
" Found corrupt space point: index " << clust.index());
1327 ATH_MSG_DEBUG(
" Inconsistent phi angle, dropping space point: phi " << spacePoint.
globalPos.phi() <<
" range " << phimin
1335 if (chamberDataVec.empty() || chamberDataVec.back().id != spacePoint.
detElId) {
1336 detElOnSegments.insert(spacePoint.
detElId);
1337 chamberDataVec.emplace_back(spacePoint.
detElId);
1339 phiIndices.insert(phiIndex);
1343 ChamberData& chamber = chamberDataVec.back();
1346 if (spacePoint.
detElId == chamber.id) {
1348 if (chamber.data.empty() || chamber.data.back().id != spacePoint.
gasGapId) {
1349 chamber.data.emplace_back(spacePoint.
gasGapId);
1355 gasGap.data.emplace_back(resPull.second, spacePoint);
1359 double posFirstPhiStation{FLT_MAX}, posLastPhiStation{0.};
1362 for (ChamberData& chamb : chamberDataVec) {
1364 std::list<const Trk::PrepRawData*> etaClusterVec{}, phiClusterVec{};
1365 std::unordered_set<Identifier> etaIds;
1372 double bestPull = std::abs(gasGap.data.front().first);
1375 unsigned int nassociatedSp = 0;
1376 GasGapData::EntryVec::const_iterator cl_it = gasGap.data.begin();
1377 while (cl_it != gasGap.data.end() && std::abs(cl_it->first) - bestPull < 1.) {
1382 << std::abs(cl_it->first) <<
" distance to segment " << dist <<
" phi "
1383 <<
sp.globalPos.phi());
1387 if (etaIds.insert(
sp.etaHit->identify()).second) {
1390 sp.etaHit->prepRawData()->localCovariance().cols() == 1) {
1391 etaClusterVec.push_back(
sp.etaHit->prepRawData());
1393 rioDistVec.emplace_back(dist,
sp.etaHit->uniqueClone());
1394 ++netaPhiHits.first.first;
1398 if (!
sp.phiHits.empty()) {
1401 std::ranges::transform(
sp.phiHits, std::back_inserter(phiClusterVec),
1403 return clus->prepRawData();
1408 rioDistVec.emplace_back(dist, phi_hit->
uniqueClone());
1409 ++netaPhiHits.first.second;
1410 phiHits.push_back(phi_hit);
1414 posFirstPhiStation = std::min(phiPos, posFirstPhiStation);
1415 posLastPhiStation = std::max(phiPos, posLastPhiStation);
1417 if (
sp.phiHits.size() > 1) refit =
false;
1429 if (!etaClusterVec.empty()) {
1430 std::unique_ptr<const CompetingMuonClustersOnTrack> etaCompCluster =
m_compClusterCreator->createBroadCluster(etaClusterVec, 0.);
1431 if (!etaCompCluster) {
1432 ATH_MSG_DEBUG(
" failed to create competing ETA ROT " << etaClusterVec.size());
1434 double dist =
distanceToSegment(segment, etaCompCluster->globalPosition(), gToStation);
1435 ++netaPhiHits.first.first;
1436 if (msgLvl(MSG::VERBOSE)) {
1438 for (
unsigned int i = 0; i < etaCompCluster->containedROTs().
size(); ++i) {
1440 " content: " <<
m_idHelperSvc->toString(etaCompCluster->containedROTs()[i]->identify()));
1443 rioDistVec.emplace_back(dist, std::move(etaCompCluster));
1450 if (!phiClusterVec.empty()) {
1451 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster =
m_compClusterCreator->createBroadCluster(phiClusterVec, 0.);
1452 if (!phiCompCluster) {
1453 ATH_MSG_DEBUG(
" failed to create competing PHI ROT " << phiClusterVec.size());
1455 double dist =
distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1456 phiHits.push_back(phiCompCluster.get());
1458 ++netaPhiHits.first.second;
1460 if (msgLvl(MSG::VERBOSE)) {
1462 for (
unsigned int i = 0; i < phiCompCluster->containedROTs().
size(); ++i) {
1464 " content: " <<
m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1470 double phiPos = isEndcap ? std::abs(phiCompCluster->globalPosition().z()) :
1471 phiCompCluster->globalPosition().perp();
1472 posFirstPhiStation = std::min(phiPos,posFirstPhiStation);
1473 posLastPhiStation = std::max(phiPos,posLastPhiStation);
1474 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1485 std::map<Identifier, std::list<const Trk::PrepRawData*> > phiClusterMap;
1487 std::set<const MuonClusterOnTrack*> selectedClusters;
1488 std::vector<const Cluster2D*> phiClusters;
1489 phiClusters.reserve(spVecs.second.size());
1492 for (
const Cluster2D& phi_clus :spVecs.second) {
1497 phiClusters.push_back(&phi_clus);
1498 selectedClusters.insert(phi_clus.
phiHit);
1501 unsigned int recoveredUnassociatedPhiHits(0);
1505 for (
const Cluster2D& rpc_clust : spVecs.first) {
1510 if (detElOnSegments.count(rpc_clust.
detElId))
continue;
1514 if (phiIndices.count(phiIndex))
continue;
1516 bool wasFound =
false;
1519 if (!selectedClusters.insert(phi_hit).second) {
1526 if (erase_me == phi_hit)
break;
1527 selectedClusters.erase(erase_me);
1532 if (wasFound)
continue;
1535 phiClusters.push_back(&rpc_clust);
1536 ++recoveredUnassociatedPhiHits;
1540 unsigned int addedPhiHits(0);
1541 for (
const Cluster2D* phi_clus : phiClusters) {
1545 if (detElOnSegments.count(detElId))
continue;
1549 if (phiIndices.count(phiIndex))
continue;
1556 double residual = resWithSegment.
residual(cl);
1557 double segError = std::sqrt(resWithSegment.
trackError2(cl));
1566 bool inBounds = std::abs(residual) < 0.5 * stripLength + 2. + segError;
1567 if (msgLvl(MSG::DEBUG)) {
1569 <<
" pos y " << cl.position().y() <<
" : residual " << residual <<
" strip half length "
1570 << 0.5 * stripLength <<
" segment error " << segError);
1578 std::list<const Trk::PrepRawData*>& cham_hits{phiClusterMap[detElId]};
1579 std::transform(phi_clus->
phiHits.begin(), phi_clus->
phiHits.end(), std::back_inserter(cham_hits),
1581 return clus->prepRawData();
1587 for (
const auto& [phi_id, prds] : phiClusterMap) {
1593 std::unique_ptr<const CompetingMuonClustersOnTrack> phiCompCluster =
m_compClusterCreator->createBroadCluster(prds, 0.);
1594 if (!phiCompCluster) {
1595 ATH_MSG_DEBUG(
" failed to create competing PHI ROT " << prds.size());
1597 double dist =
distanceToSegment(segment, phiCompCluster->globalPosition(), gToStation);
1602 <<
" distance to segment " << dist);
1605 phiHits.push_back(phiCompCluster.get());
1606 ++netaPhiHits.first.second;
1608 if (msgLvl(MSG::VERBOSE)) {
1610 <<
" distance to segment " << dist);
1611 for (
unsigned int i = 0; i < phiCompCluster->containedROTs().
size(); ++i) {
1613 " content: " <<
m_idHelperSvc->toString(phiCompCluster->containedROTs()[i]->identify()));
1616 rioDistVec.emplace_back(dist, std::move(phiCompCluster));
1619 ATH_MSG_VERBOSE(
"Added " << addedPhiHits <<
" unass phi hits out of " << spVecs.second.size()
1620 <<
" phi hits without eta hit and " << recoveredUnassociatedPhiHits <<
" with unassociated eta hit ");
1624 double phiDistanceMax = posLastPhiStation - posFirstPhiStation;
1625 if (isEndcap && phiDistanceMax < 1000.)
1627 else if (phiDistanceMax < 400.)
1630 netaPhiHits.second = refit;
1638 double cos_sinLine = cot(line.phi());
1646 double delta_y = lpos.
y() - line.position().y();
1654 return pointOnHit.
x();
1658 std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec) {
1663 rioVec.
reserve(rioDistVec.size());
1664 for (std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) { rioVec.
push_back(std::move(rdit.second)); }
1673 double cos_sinLine = cot(line.phi());
1680 double delta_y = lpos.
y() - line.position().y();
1686 double residual = lpos.
x() - lineSurfaceIntersect.
x();
1687 double pull = residual / spacePoint.
error;
1688 return std::make_pair(residual, pull);
1693 std::set<Identifier>& outoftimeVec,
const std::vector<std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>> >& rioDistVec)
const {
1696 if (!InterSectSvc.
isValid()) {
1697 ATH_MSG_ERROR(
"Null pointer to the read MuonDetectorManager conditions object");
1703 const MuonStationIntersect intersect = InterSectSvc->tubesCrossedByTrack(MuonDetMgr, chid, gpos, gdir);
1706 std::set<Identifier> hitsOnSegment, chambersOnSegment;
1707 int firstLayer{-1}, lastLayer{-1};
1708 for (
const std::pair<
double, std::unique_ptr<const Trk::MeasurementBase>>& rdit : rioDistVec) {
1713 if (firstLayer == -1)
1718 hitsOnSegment.insert(
id);
1723 if (firstLayer > lastLayer) {
std::swap(firstLayer, lastLayer); }
1724 ATH_MSG_VERBOSE(
" Tube layer ranges: " << firstLayer <<
" -- " << lastLayer <<
" crossed tubes "
1725 << intersect.tubeIntersects().size());
1727 std::vector<Identifier> holeVec;
1729 if (!chambersOnSegment.count(
m_idHelperSvc->chamberId(tint.tubeId))) {
1730 ATH_MSG_VERBOSE(
" chamber not on segment, not counting tube " << tint.rIntersect <<
" l " << tint.xIntersect <<
" "
1738 bool notBetweenHits = layer < firstLayer || layer > lastLayer;
1739 double distanceCut = hasMeasuredCoordinate ? -20 : -200.;
1741 if (notBetweenHits && (std::abs(tint.rIntersect) > innerRadius || (!
m_allMdtHoles && tint.xIntersect > distanceCut))) {
1742 ATH_MSG_VERBOSE(
" not counting tube: distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1747 if (hitsOnSegment.count(tint.tubeId)) {
1748 ATH_MSG_VERBOSE(
" tube on segment: distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1754 if (deltaVec.count(tint.tubeId)) {
1755 ATH_MSG_VERBOSE(
" removing delta, distance to wire " << tint.rIntersect <<
" dist to tube end " << tint.xIntersect
1762 ATH_MSG_VERBOSE(
" found and removed delta, distance to wire " << tint.rIntersect <<
" dist to tube end "
1763 << tint.xIntersect <<
" "
1768 ATH_MSG_VERBOSE((outoftimeVec.count(tint.tubeId) ?
"Out-of-time" :
"hole") <<
" distance to wire "
1769 << tint.rIntersect <<
" dist to tube end " << tint.xIntersect <<
" "
1770 <<
m_idHelperSvc->toString(tint.tubeId)<<(notBetweenHits ?
"outside hits" :
"between hits"));
1772 holeVec.push_back(tint.tubeId);
1789 if (!collptr)
return nullptr;
1791 if (prd->identify() ==
id)
return prd;
1797 const std::vector<const MdtDriftCircleOnTrack*>& mdts)
const {
1798 int hitsInChamberWithMostHits = 0;
1799 std::map<Identifier, int> hitsPerChamber;
1800 int currentSector = -1;
1811 if (currentSector == -1) {
1812 currentSector = sector;
1813 }
else if (sector != currentSector) {
1816 int& hitsInCh = hitsPerChamber[chId];
1818 if (hitsInCh > hitsInChamberWithMostHits) {
1819 hitsInChamberWithMostHits = hitsInCh;
1820 rotInChamberWithMostHits = rot;
1823 return rotInChamberWithMostHits;
1827 const std::vector<DCMathSegmentMaker::HitInXZ>& hits)
const {
1831 for (
const HitInXZ& hit : hits) {
1832 bool outBounds =
false;
1833 double locExX = xline + dXdZ * (hit.z - zline);
1834 if (hit.isMdt && (locExX < hit.xmin - 1. || locExX > hit.xmax + 1.)) {
1837 if (!msgLvl(MSG::DEBUG))
break;
1840 if (outBounds && msgLvl(MSG::DEBUG)) {
1842 << std::setw(6) << (
int)hit.z <<
") ex pos " << std::setw(6) << (
int)locExX <<
" min " << std::setw(6)
1843 << (
int)hit.xmin <<
" max " << std::setw(6) << (
int)hit.xmax <<
" phimin " << std::setw(6)
1844 << hit.phimin <<
" phimax " << std::setw(6) << hit.phimax <<
" outBounds, cross-check");
1852 const std::vector<const Trk::MeasurementBase*>& rots,
double seg_phimin,
1853 double seg_phimax)
const {
1854 bool hasUpdated =
false;
1861 if (ldir.z() < 0.0001)
return false;
1863 double dXdZ = ldir.x() / ldir.z();
1865 double xline = lsegPos.x();
1866 double zline = lsegPos.z();
1867 ATH_MSG_VERBOSE(
" Associated hits " << rots.size() <<
" angleXZ " << 90. * segLocDir.
angleXZ() / (M_PI_2) <<
" dXdZ " << dXdZ
1868 <<
" seg Pos (" << xline <<
" " << zline <<
") " << segLocPos);
1870 std::vector<HitInXZ> hits;
1871 hits.reserve(rots.size());
1873 unsigned int nphiHits(0);
1874 const HitInXZ* firstPhiHit{
nullptr}, *lastPhiHit{
nullptr};
1878 if (!
id.is_valid())
continue;
1880 double lxmin{0}, lxmax{0}, phimin{0}, phimax{0};
1888 lxmin = tubeEnds.
lxmin;
1889 lxmax = tubeEnds.
lxmax;
1890 phimin = tubeEnds.
phimin;
1891 phimax = tubeEnds.
phimax;
1893 lpos = gToSegment * meas->globalPosition();
1905 lxmin = lpos.x() - 0.5 * stripLength;
1906 lxmax = lpos.x() + 0.5 * stripLength;
1910 locPosition[0] = lxmin;
1912 double phi1 = globalPos.phi();
1914 locPosition[0] = lxmax;
1915 globalPos = segmentToGlobal * locPosition;
1916 double phi2 = globalPos.phi();
1917 phimin = std::min(phi1, phi2);
1918 phimax = std::max(phi1, phi2);
1930 ATH_MSG_WARNING(
"dynamic cast failed for CompetingMuonClustersOnTrack");
1936 const Amg::Vector3D segFrame_StripDir = gToSegment.linear()* detEl->stripDir(gasGap, stripNo);
1937 const Amg::Vector3D segFrame_stripPos = gToSegment * detEl->channelPos(
id);
1939 lpos = segFrame_stripPos +
1940 Amg::intersect<3>(lsegPos, ldir, segFrame_stripPos, segFrame_StripDir).value_or(0) * segFrame_StripDir;
1947 phimin = globalPos.phi();
1953 ATH_MSG_DEBUG(
" Inconsistent phi " << phimin <<
" range " << seg_phimin <<
" " << seg_phimax);
1958 hits.emplace_back(
id, isMdt, measuresPhi, lpos.x(), lpos.z(), lxmin, lxmax, phimin, phimax);
1962 firstPhiHit = &hits.back();
1964 double distPhiHits = std::abs(firstPhiHit->
z - hits.back().z);
1965 if (distPhiHits > 500.) {
1966 lastPhiHit = &hits.back();
1974 if (msgLvl(MSG::VERBOSE)) {
1975 double locExX = xline + dXdZ * (lpos.z() - zline);
1977 << std::setw(6) << (
int)lpos.z() <<
") ex pos " << std::setw(6) << (
int)locExX <<
" min "
1978 << std::setw(6) << (
int)lxmin <<
" max " << std::setw(6) << (
int)lxmax <<
" phimin " << std::setw(6)
1979 << phimin <<
" phimax " << std::setw(6) << phimax);
1980 if (lpos.x() < lxmin || lpos.x() > lxmax)
ATH_MSG_VERBOSE(
" outBounds");
1984 if (nphiHits == 1) {
1986 ATH_MSG_WARNING(
" Pointer to first phi hit not set, this should not happen! ");
1988 if (xline != firstPhiHit->
x) {
1992 xline = firstPhiHit->
x;
1993 zline = firstPhiHit->
z;
1999 double dz = ipLocPos.z() - zline;
2000 if (std::abs(dz) > 0.001) {
2001 ATH_MSG_VERBOSE(
" hit (" << xline <<
"," << zline <<
") IP (" << ipLocPos.x() <<
"," << ipLocPos.z()
2002 <<
") dXdZ " << (ipLocPos.x() - xline) / dz <<
" old " << dXdZ);
2003 dXdZ = (ipLocPos.x() - xline) / dz;
2008 }
else if (nphiHits == 2) {
2009 if (!firstPhiHit || !lastPhiHit) {
2010 ATH_MSG_WARNING(
" Pointer to one of the two phi hit not set, this should not happen! ");
2012 double dz = lastPhiHit->z - firstPhiHit->
z;
2014 xline = firstPhiHit->
x;
2015 zline = firstPhiHit->
z;
2016 if (std::abs(dz) > 300.) {
2017 double dx = lastPhiHit->x - firstPhiHit->
x;
2030 double segX = xline - dXdZ * zline;
2036 ATH_MSG_DEBUG(
"still several out of bounds hits after rotation: posx(" << segX <<
") dXdZ " << dXdZ
2037 <<
" keeping old result ");
2041 double alphaYZ = segLocDir.
angleYZ();
2042 double alphaXZ = std::atan2(1, dXdZ);
2061 double tubeLen = (lropos - lhvpos).
mag();
2062 double activeTubeLen =
2064 double scaleFactor = activeTubeLen / tubeLen;
2065 lropos[0] = scaleFactor * lropos.x();
2066 lhvpos[0] = scaleFactor * lhvpos.x();
2068 tubeEnds.
lxmin = std::min(lropos.x(), lhvpos.x());
2069 tubeEnds.
lxmax = std::max(lropos.x(), lhvpos.x());
2073 const double phiRO = ropos.phi();
2074 const double phiHV = hvpos.phi();
2075 tubeEnds.
phimin = std::min(phiRO, phiHV);
2076 tubeEnds.
phimax = std::max(phiRO, phiHV);
2082 if (phiminRef * phimaxRef < 0.) {
2083 if (phiminRef < -1.1) {
2084 if (phiminRef > phiminNew) phiminRef = phiminNew;
2085 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2087 if (phiminRef < phiminNew) phiminRef = phiminNew;
2088 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2092 if (phiminRef < 0.) {
2093 if (phiminRef < phiminNew) phiminRef = phiminNew;
2094 if (phimaxRef > phimaxNew) phimaxRef = phimaxNew;
2096 if (phiminRef > phiminNew) phiminRef = phiminNew;
2097 if (phimaxRef < phimaxNew) phimaxRef = phimaxNew;
2107 double offset = 0.05;
2108 if (phimin * phimax < 0.) {
2111 if (
phi < phimin - offset) phiOk =
false;
2113 if (
phi > phimin + offset) phiOk =
false;
2117 if (
phi < phimax - offset) phiOk =
false;
2119 if (
phi > phimax + offset) phiOk =
false;
2129 bool isCurvedSegment)
const {
2141 double dx = std::sin(gdirs.theta()) * std::cos(gdirs.phi());
2142 double dy = std::sin(gdirs.theta()) * std::sin(gdirs.phi());
2143 double dz = std::cos(gdirs.theta());
2147 double dxo = std::sin(gdiro.theta()) * std::cos(gdiro.phi());
2148 double dyo = std::sin(gdiro.theta()) * std::sin(gdiro.phi());
2149 double dzo = std::cos(gdiro.theta());
2157 double a0 = dx * std::sin(roaddir.phi()) - dy * std::cos(roaddir.phi());
2158 double b0 = dxo * std::sin(roaddir.phi()) - dyo * std::cos(roaddir.phi());
2159 if (b0 < 1e-8 && b0 > 0) b0 = 1e-8;
2160 if (b0 > -1e-8 && b0 < 0) b0 = -1e-8;
2161 double dxn = dx -
a0 * dxo / b0;
2162 double dyn = dy -
a0 * dyo / b0;
2163 double dzn = dz -
a0 * dzo / b0;
2164 double norm = std::sqrt(dxn * dxn + dyn * dyn + dzn * dzn);
2168 if (dxn * roaddir.x() + dyn * roaddir.y() + dzn * roaddir.z() < 0.) { norm = -norm; }
2170 if (dxn * roaddir.x() + dyn * roaddir.y() < 0.) { norm = -norm; }
2173 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)
size_t size() const
Number of registered mappings.
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< std::unique_ptr< 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)