10#include "GaudiKernel/ConcurrencyFlags.h"
31 constexpr double inverseSpeedOfLight = 1 / Gaudi::Units::c_light;
38 std::ostringstream sout;
39 sout <<
" sector " <<
intersection.layerSurface.sector <<
" "
70 return StatusCode::SUCCESS;
79 extend(inDetCandidates, tagMap, combTracks, meTracks, segments, ctx);
84 const EventContext& ctx)
const {
87 if (meTracks)
ATH_MSG_DEBUG(
"Not currently creating ME tracks for staus");
91 std::unique_ptr<MuonStauRecoTool::TruthInfo>
95 truthParticleLinkAcc(
"truthParticleLink");
99 return std::make_unique<TruthInfo>((*truthLink)->pdgId(), (*truthLink)->m(), (*truthLink)->p4().Beta());
108 ATH_MSG_DEBUG(
" skip silicon associated track for extension ");
121 std::unique_ptr<TruthInfo> truthInfo(
getTruth(indetTrackParticle));
125 ATH_MSG_DEBUG(
"Truth reconstruction enabled: skipping ID track with pdgId: " << (truthInfo ? truthInfo->pdgId : 0));
134 msg(MSG::INFO) <<
" ID track: pt " << indetTrackParticle.
pt() <<
" eta " << indetTrackParticle.
eta() <<
" phi "
135 << indetTrackParticle.
phi();
136 if (truthInfo)
msg(MSG::INFO) << truthInfo->toString();
137 if (!muonSystemExtension)
msg(MSG::INFO) <<
" failed muonSystemExtension";
142 if (!muonSystemExtension) {
return; }
187 addTag(indetCandidate, *candidates.front(), tagMap, combTracks, segments);
196 for (
auto& candidate : candidates) {
197 ATH_MSG_DEBUG(
" candidate: betaseed beta" << candidate->betaSeed.beta <<
", error" << candidate->betaSeed.error
198 <<
" layerDataVec size" << candidate->layerDataVec.size() <<
" hits size"
199 << candidate->hits.size());
201 float beta = candidate->betaFitResult.beta;
203 for (
const auto& layerData : candidate->layerDataVec) {
205 std::vector<std::shared_ptr<const Muon::MuonSegment>> segments;
208 for (
const auto& maximumData : layerData.maximumDataVec) {
214 if (segments.empty())
continue;
222 std::vector<std::shared_ptr<const Muon::MuonSegment>> selectedSegments;
226 for (
const auto& seg : selectedSegments)
m_recoValidationTool->add(layerData.intersection, *seg, 3);
230 candidate->allLayers.emplace_back(layerData.intersection, std::move(selectedSegments));
234 if (!candidate->allLayers.empty()) refinedCandidates.push_back(candidate);
238 candidates = refinedCandidates;
242 msg(MSG::INFO) <<
" Summary::refineCandidates ";
243 if (candidates.empty())
244 msg(MSG::INFO) <<
" No candidated found ";
246 msg(MSG::INFO) <<
" candidates " << candidates.size();
248 for (
const auto& candidate : candidates) {
249 msg(MSG::INFO) << std::endl
250 <<
" candidate: beta fit result: beta " << candidate->betaFitResult.beta <<
" chi2/ndof "
251 << candidate->betaFitResult.chi2PerDOF() <<
" layers with segments" << candidate->allLayers.size();
252 for (
const auto& layer : candidate->allLayers)
253 msg(MSG::INFO) << std::endl
259 return !candidates.empty();
266 if (!mdtCalibConstants.
isValid()) {
268 throw std::runtime_error(
"Failed to retrieve calibration constants");
272 if (!combinedTrack)
return;
284 ATH_MSG_WARNING(
" track without states, cannot extractTimeMeasurementsFromTrack ");
291 typedef std::vector<const Muon::MuonClusterOnTrack*> RpcClVec;
292 using RpcClPerChMap = std::map<Identifier, std::tuple<const Trk::TrackParameters*, RpcClVec, RpcClVec>>;
293 RpcClPerChMap rpcPrdsPerChamber;
295 using MdtTubeData = std::pair<const Trk::TrackParameters*, const Muon::MdtDriftCircleOnTrack*>;
296 using MdtTubeDataVec = std::vector<MdtTubeData>;
297 using MdtChamberLayerData = std::map<int, MdtTubeDataVec>;
298 MdtChamberLayerData mdtDataPerChamberLayer;
303 for (; tsit != tsit_end; ++tsit) {
325 if (
stName[2] ==
'R') { chIndexWithBIR += 1000; }
327 mdtDataPerChamberLayer[chIndexWithBIR].push_back(std::make_pair(pars, mdt));
330 float distance = pars->position().mag();
333 float ix = pars->position().x();
334 float iy = pars->position().y();
335 float iz = pars->position().z();
345 float locR = pars->parameters()[
Trk::locR];
347 auto data = mdtCalibConstants->getCalibData(
id, msgStream());
348 const auto& rtRelation =
data->rtRelation;
349 float drdt = rtRelation->rt()->driftVelocity(driftTime);
350 float rres = rtRelation->rtRes()->resolution(driftTime);
351 float tres = rres / drdt;
352 float TlocR = rtRelation->tr()->driftTime(std::abs(locR)).value_or(0.);
353 float trackTimeRes = errR / drdt;
354 float tofShiftFromBeta =
calculateTof(betaSeed, distance) - tof;
355 er = std::sqrt(tres * tres + trackTimeRes * trackTimeRes);
357 time = driftTime - TlocR + tofShiftFromBeta;
358 propTime = driftTime;
362 std::unique_ptr<const Trk::TrackParameters> unbiasedPars(
365 float locRu = unbiasedPars->parameters()[
Trk::locR];
366 float TlocRu = rtRelation->tr()->driftTime(std::abs(locRu)).value_or(0.);
367 float errRu = unbiasedPars->covariance() ?
Amg::error(*unbiasedPars->covariance(),
Trk::locR) : 0.3;
368 float trackTimeResu = errRu / drdt;
370 time = driftTime - TlocRu + tofShiftFromBeta;
371 er = std::sqrt(tres * tres + trackTimeResu * trackTimeResu);
373 ATH_MSG_VERBOSE(
" Got unbiased parameters: r " << locR <<
" ur " << locRu <<
" err " << errR <<
" uerr "
374 << errRu <<
" terr " << trackTimeRes <<
" terru "
380 <<
" TlocR " << TlocR <<
" diff " << driftTime - TlocR <<
" tofShift " << tofShiftFromBeta
381 <<
" time " << time <<
" err " << er <<
" intrinsic " << tres <<
" track " << trackTimeRes);
385 << beta <<
" diff " << std::abs(beta - betaSeed));
388 candidate.
stauHits.emplace_back(
MuGirlNS::StauHit(tech, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime,
false));
399 candidate.
stauHits.emplace_back(
MuGirlNS::StauHit(tech, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime,
true));
409 std::vector<const Muon::MuonClusterOnTrack*> clusters;
412 std::ranges::transform(crot->
containedROTs(), std::back_inserter(clusters),
418 if (rpc) clusters.push_back(rpc);
422 auto pos = rpcPrdsPerChamber.find(chamberId);
423 if (pos == rpcPrdsPerChamber.end()) {
425 rpcPrdsPerChamber[chamberId] = std::make_tuple(pars, clusters, RpcClVec());
427 rpcPrdsPerChamber[chamberId] = std::make_tuple(pars, RpcClVec(), clusters);
429 RpcClVec& clVec = measuresPhi ? std::get<1>(pos->second) : std::get<2>(pos->second);
430 clVec.insert(clVec.end(), clusters.begin(), clusters.end());
436 float distance = pars->position().mag();
439 float ix = pars->position().x();
440 float iy = pars->position().y();
441 float iz = pars->position().z();
448 candidate.
stauHits.push_back(
MuGirlNS::StauHit(tech, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime));
454 if (clusters.empty())
return;
456 std::vector<const Muon::MuonClusterOnTrack*> calibratedClusters;
457 for (
const auto* cluster : clusters) {
459 if (cl) calibratedClusters.push_back(cl);
461 if (calibratedClusters.empty())
return;
464 for (
const auto* cl : calibratedClusters)
delete cl;
465 if (!result.valid)
return;
470 float distance = pars.position().mag();
471 float time = result.time;
472 float ix = pars.position().x();
473 float iy = pars.position().y();
474 float iz = pars.position().z();
476 float er = result.error;
485 <<
" diff " << std::abs(beta - betaSeed));
490 candidate.
stauHits.push_back(
MuGirlNS::StauHit(tech, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime));
494 RpcClPerChMap::const_iterator chit = rpcPrdsPerChamber.begin();
495 RpcClPerChMap::const_iterator chit_end = rpcPrdsPerChamber.end();
498 for (; chit != chit_end; ++chit) {
500 const RpcClVec& phiClusters = std::get<1>(chit->second);
501 const RpcClVec& etaClusters = std::get<2>(chit->second);
502 insertRpcs(*pars, phiClusters, candidate, hits);
503 insertRpcs(*pars, etaClusters, candidate, hits);
518 MdtChamberLayerData::const_iterator mit = mdtDataPerChamberLayer.begin();
519 MdtChamberLayerData::const_iterator mit_end = mdtDataPerChamberLayer.end();
520 for (; mit != mit_end; ++mit) {
522 <<
" hits " << mit->second.size());
523 if (mit->second.size() < 4)
continue;
529 ATH_MSG_WARNING(
"MdtReadoutElement should always have a PlaneSurface as reference surface");
546 std::vector<std::pair<std::shared_ptr<const Muon::MdtDriftCircleOnTrack>,
const Trk::TrackParameters*>> indexLookUp;
548 for (
const auto& entry : mit->second) {
553 std::unique_ptr<const Muon::MdtDriftCircleOnTrack> calibratedMdt(
555 if (!calibratedMdt) {
562 <<
" r_track " << pars.parameters()[
Trk::locR] <<
" residual "
574 double r = std::abs(calibratedMdt->driftRadius());
585 dcs.push_back(dcOnTrack);
586 indexLookUp.emplace_back(std::move(calibratedMdt), &pars);
591 for (
unsigned int i = 0; i < dcs.size(); ++i) {
601 unsigned int ndofFit = segment.
ndof();
602 if (ndofFit < 1)
continue;
603 double chi2NdofSegmentFit = segment.
chi2() / ndofFit;
604 bool hasDropHit =
false;
605 unsigned int dropDepth = 0;
606 if (!segmentFinder.
dropHits(segment, hasDropHit, dropDepth)) {
607 ATH_MSG_DEBUG(
"DropHits failed, fit chi2/ndof " << chi2NdofSegmentFit);
608 if (
msgLvl(MSG::VERBOSE)) {
611 segmentFinder.
dropHits(segment, hasDropHit, dropDepth);
616 if (i >= segment.
dcs().size())
continue;
621 double pull =
res / err;
624 if (index < 0 || index >= (
int)indexLookUp.size()) {
625 ATH_MSG_WARNING(
" lookup of TrackParameters and MdtDriftCircleOnTrack failed " <<
index <<
" range: 0 - "
626 << indexLookUp.size() - 1);
634 std::shared_ptr<const Muon::MdtDriftCircleOnTrack> calibratedMdt(
636 if (!calibratedMdt.get()) {
640 float distance = pars->position().mag();
643 float ix = pars->position().x();
644 float iy = pars->position().y();
645 float iz = pars->position().z();
657 float driftTime = calibratedMdt->driftTime();
660 auto data = mdtCalibConstants->getCalibData(
id, msgStream());
661 const auto& rtRelation =
data->rtRelation;
662 float drdt = rtRelation->rt()->driftVelocity(driftTime);
663 float rres = rtRelation->rtRes()->resolution(driftTime);
664 float tres = rres / drdt;
665 float TlocR = rtRelation->tr()->driftTime(std::abs(locR)).value_or(0.);
666 float trackTimeRes = errR / drdt;
667 float tofShiftFromBeta = 0.;
668 er = std::sqrt(tres * tres + trackTimeRes * trackTimeRes);
670 time = driftTime - TlocR + tofShiftFromBeta;
671 propTime = driftTime;
678 msg(MSG::DEBUG) <<
m_idHelperSvc->toString(
id) << std::setprecision(2) <<
" segment: after fit " << std::setw(5)
679 << chi2NdofSegmentFit <<
" ndof " << std::setw(2) << ndofFit;
680 if (segment.
ndof() != ndofFit)
681 msg(MSG::DEBUG) <<
" after outlier " << std::setw(5) << chi2NdofSegmentFit <<
" ndof " << std::setw(2) << ndofFit;
682 msg(MSG::DEBUG) <<
" driftR " << std::setw(4) << dc.
r() <<
" rline " << std::setw(5) << rline <<
" residual "
683 << std::setw(5) <<
res <<
" pull " << std::setw(4) << pull <<
" time " << std::setw(3) << time
684 <<
" beta" << std::setw(2) << beta <<
" err " << std::setw(3) << er <<
" intrinsic " << std::setw(3)
685 << tres <<
" track " << std::setw(3) << trackTimeRes;
686 if (!isSelected)
msg(MSG::DEBUG) <<
" outlier";
687 msg(MSG::DEBUG) << std::setprecision(5) <<
endmsg;
692 candidate.
stauHits.emplace_back(
MuGirlNS::StauHit(
MuGirlNS::MDTT_STAU_HIT, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime,
false));
702 hits.emplace_back(distance, time, er);
703 candidate.
stauHits.emplace_back(
MuGirlNS::MDTT_STAU_HIT, time + tof, ix, iy, iz,
id, ie, er,
sh, isEta, propTime,
true);
711 ATH_MSG_DEBUG(
" extractTimeMeasurementsFromTrack: extracted " << candidate.
stauHits.size() <<
" time measurements "
712 <<
" status fit " << betaFitResult.
status <<
" beta "
713 << betaFitResult.
beta <<
" chi2/ndof " << betaFitResult.
chi2PerDOF());
726 std::vector<ElementLink<Trk::SegmentCollection>> segmentLinks;
727 for (
const auto& layer : candidate.
allLayers) {
728 for (
const auto& segment : layer.segments) {
731 segmentLinks.push_back(segLink);
742 std::unique_ptr<MuGirlNS::StauExtras> stauExtras = std::make_unique<MuGirlNS::StauExtras>();
745 stauExtras->hits = candidate.
stauHits;
751 tag->setStauExtras(std::move(stauExtras));
755 msg(MSG::INFO) <<
" Summary::addTag ";
756 msg(MSG::INFO) << std::endl
757 <<
" candidate: beta fit result: beta " << candidate.
betaFitResult.
beta <<
" chi2/ndof "
759 for (
const auto& segment : segmentLinks)
msg(MSG::INFO) << std::endl <<
" " <<
m_printer->print(**segment);
761 msg(MSG::INFO) << std::endl
762 <<
" track " <<
m_printer->print(**comblink) << std::endl
768 tagMap->
addEntry(&indetCandidate, tag);
772 ATH_MSG_DEBUG(
"Resolving ambiguities: candidates " << candidates.size());
776 std::map<const Trk::Track*, std::shared_ptr<Candidate>> trackCandidateLookup;
777 for (
const auto& candidate : candidates) {
778 Trk::Track* track = candidate->combinedTrack.get();
781 trackCandidateLookup[track] = candidate;
786 if (tracks.
empty())
return false;
787 if (tracks.
size() == 1)
return true;
791 if (!resolvedTracks || resolvedTracks->empty()) {
795 const Trk::Track* selectedTrack = resolvedTracks->front();
798 auto pos = trackCandidateLookup.find(selectedTrack);
799 if (pos == trackCandidateLookup.end()) {
805 std::shared_ptr<Candidate> candidate = pos->second;
807 candidates.push_back(candidate);
811 msg(MSG::INFO) <<
" Summary::resolveAmbiguities ";
812 msg(MSG::INFO) << std::endl
813 <<
" candidate: beta fit result: beta " << candidate->betaFitResult.beta <<
" chi2/ndof "
814 << candidate->betaFitResult.chi2PerDOF() <<
" layers with segments" << candidate->allLayers.size() << std::endl
815 <<
" track " <<
m_printer->print(*candidate->combinedTrack) << std::endl
816 <<
m_printer->printStations(*candidate->combinedTrack);
830 for (
auto& candidate : candidates) {
832 std::pair<std::unique_ptr<const Muon::MuonCandidate>, std::unique_ptr<Trk::Track>> result =
835 if (result.first && result.second) {
837 <<
m_printer->print(*result.second) << std::endl
838 <<
m_printer->printStations(*result.second));
840 candidate->muonCandidate = std::move(result.first);
841 candidate->combinedTrack = std::move(result.second);
845 combinedCandidates.push_back(candidate);
851 candidates = combinedCandidates;
855 msg(MSG::INFO) <<
" Summary::combineCandidates ";
856 if (candidates.empty())
857 msg(MSG::INFO) <<
" No candidated found ";
859 msg(MSG::INFO) <<
" candidates " << candidates.size();
861 for (
const auto& candidate : candidates) {
862 msg(MSG::INFO) << std::endl
863 <<
" candidate: beta fit result: " << candidate->betaFitResult.beta <<
" chi2/ndof "
864 << candidate->betaFitResult.chi2PerDOF();
865 if (candidate->finalBetaFitResult.status != 0)
866 msg(MSG::INFO) <<
" MDTT beta fit result: " << candidate->finalBetaFitResult.beta <<
" chi2/ndof "
867 << candidate->finalBetaFitResult.chi2PerDOF();
868 msg(MSG::INFO) <<
" layers with segments" << candidate->allLayers.size() << std::endl
869 <<
" track " <<
m_printer->print(*candidate->combinedTrack) << std::endl
870 <<
m_printer->printStations(*candidate->combinedTrack);
875 return !candidates.empty();
882 LayerDataVec::const_iterator it = associatedData.
layerData.begin();
883 LayerDataVec::const_iterator it_end = associatedData.
layerData.end();
884 for (; it != it_end; ++it) {
886 for (
const auto& maximumData : it->maximumDataVec) {
888 if (!maximumData->betaSeeds.empty()) seedMaximumDataVec.push_back(maximumData);
891 ATH_MSG_DEBUG(
"Creating candidates from seeds " << seedMaximumDataVec.size());
893 if (seedMaximumDataVec.empty()) {
899 auto SortMaximumDataVec = [](
const std::shared_ptr<MaximumData>& max1,
const std::shared_ptr<MaximumData>& max2) {
900 return max1->maximum->max < max2->maximum->max;
902 std::stable_sort(seedMaximumDataVec.begin(), seedMaximumDataVec.end(), SortMaximumDataVec);
906 std::set<const MaximumData*> usedMaximumData;
907 MaximumDataVec::iterator sit = seedMaximumDataVec.begin();
908 MaximumDataVec::iterator sit_end = seedMaximumDataVec.end();
909 for (; sit != sit_end; ++sit) {
911 if (usedMaximumData.count(sit->get()))
continue;
912 usedMaximumData.insert(sit->get());
916 for (
const auto& betaSeed : (*sit)->betaSeeds) { newCandidates.push_back(std::make_shared<Candidate>(betaSeed)); }
921 for (
auto& newCandidate : newCandidates) {
923 newCandidate->betaFitResult = fitter.fitWithOutlierLogic(newCandidate->hits);
925 << newCandidate->hits.size() <<
" status " << newCandidate->betaFitResult.status <<
" beta "
926 << newCandidate->betaFitResult.beta <<
" chi2/ndof " << newCandidate->betaFitResult.chi2PerDOF());
928 if (newCandidate->betaFitResult.status != 0) {
929 newCandidate->combinedTrack =
nullptr;
930 candidates.push_back(newCandidate);
937 msg(MSG::INFO) <<
" Summary::createCandidates ";
938 if (candidates.empty())
939 msg(MSG::INFO) <<
" No candidated found ";
941 msg(MSG::INFO) <<
" candidates " << candidates.size();
943 for (
const auto& candidate : candidates) {
944 msg(MSG::INFO) << std::endl
945 <<
" candidate: beta seed " << candidate->betaSeed.beta <<
" beta fit result: beta "
946 << candidate->betaFitResult.beta <<
" chi2/ndof " << candidate->betaFitResult.chi2PerDOF() <<
" layers "
947 << candidate->layerDataVec.size();
948 for (
const auto& layerData : candidate->layerDataVec)
949 msg(MSG::INFO) << std::endl
951 << layerData.maximumDataVec.size();
956 return !candidates.empty();
960 MuonStauRecoTool::LayerDataVec::const_iterator it,
961 MuonStauRecoTool::LayerDataVec::const_iterator it_end)
const {
968 for (
auto& candidate : candidates) {
970 unsigned int nextensions = 0;
983 if (nextensions == 0)
984 theCandidate = candidate.get();
986 std::shared_ptr<Candidate> newCandidate = std::make_shared<Candidate>(candidate->betaSeed);
987 newCandidate->layerDataVec = layerDataVec;
988 newCandidate->hits = hits;
989 theCandidate = newCandidate.get();
990 newCandidates.emplace_back(std::move(newCandidate));
998 theCandidate->
hits.insert(theCandidate->
hits.end(), newhits.begin(), newhits.end());
1000 usedMaximumData.insert(maximumData.get());
1002 ATH_MSG_DEBUG(
" adding maximumData: candidate hits " << theCandidate->
hits.size() <<
" LayerDataVec "
1003 << theCandidate->
layerDataVec.size() <<
" nextensions "
1010 ATH_MSG_DEBUG(
" extendCandidates done, new candidates " << newCandidates.size());
1013 candidates.insert(candidates.end(), newCandidates.begin(), newCandidates.end());
1017 if (it != it_end)
extendCandidates(candidates, usedMaximumData, it, it_end);
1033 associatedData.
layerData.push_back(layerData);
1041 std::vector<std::shared_ptr<const Muon::MuonSegment>> t0fittedSegments;
1043 if (t0fittedSegments.empty())
continue;
1055 msg(MSG::INFO) <<
" Summary::extractTimeMeasurements ";
1057 msg(MSG::INFO) <<
" No layers associated ";
1059 msg(MSG::INFO) <<
" Associated layers " << associatedData.
layerData.size();
1061 for (
const auto& layerData : associatedData.
layerData) {
1062 unsigned int nmaxWithBeta = 0;
1063 for (
const auto& maximumData : layerData.maximumDataVec) {
1064 if (!maximumData->betaSeeds.empty()) ++nmaxWithBeta;
1066 msg(MSG::INFO) << std::endl
1068 << layerData.maximumDataVec.size() <<
" maxima with beta seeds " << nmaxWithBeta;
1074 return !associatedData.
layerData.empty();
1079 unsigned int nstart = hits.size();
1081 auto addHit = [&](
float distance,
float time,
float error,
float cut) {
1084 ATH_MSG_VERBOSE(
" matching hit: distance " << distance <<
" time " << time <<
" beta" << beta <<
" diff "
1085 << std::abs(beta - seed->beta));
1086 if (std::abs(beta - seed->beta) > cut)
return;
1088 ATH_MSG_VERBOSE(
" addHit: distance " << distance <<
" time " << time <<
" beta"
1091 if (
error != 0.) hits.emplace_back(distance, time,
error);
1096 float time = rpc.time;
1097 float error = rpc.error;
1106 if (!seg->hasFittedT0())
continue;
1107 float time = seg->time();
1108 float error = seg->errorTime();
1116 float smallestResidual = FLT_MAX;
1118 if (!seg->hasFittedT0())
continue;
1119 float distance = seg->globalPosition().mag();
1120 float time = seg->time();
1122 float residual = std::abs(beta - seed->beta);
1124 if (residual < smallestResidual) {
1125 smallestResidual = residual;
1126 bestSegment = seg.get();
1134 ATH_MSG_VERBOSE(
" extractTimeHits done: added " << hits.size() - nstart <<
" hits");
1136 return nstart != hits.size();
1149 float chi2ndof = result.chi2PerDOF();
1151 ATH_MSG_DEBUG(
" fitting beta for maximum: time measurements " << hits.size() <<
" status " << result.status <<
" beta "
1152 << result.beta <<
" chi2/ndof " << chi2ndof);
1153 if (result.status != 0) maximumData.
betaSeeds.emplace_back(result.beta, 1.);
1157 std::vector<std::shared_ptr<const Muon::MuonSegment>>& segments,
1158 const ToolHandle<Muon::IMuonPRDSelectionTool>& muonPRDSelectionTool,
1159 const ToolHandle<Muon::IMuonSegmentMaker>& segmentMaker,
1162 const std::vector<std::shared_ptr<const Muon::MuonClusterOnTrack>>& phiClusterOnTracks = maximumData.
phiClusterOnTracks;
1166 std::vector<const Muon::MdtDriftCircleOnTrack*>& mdts,
1169 if (mdt) mdts.push_back(mdt);
1174 std::vector<const Muon::MuonClusterOnTrack*>& clusters) {
1176 if (cluster) clusters.push_back(cluster);
1180 std::vector<const Muon::MdtDriftCircleOnTrack*> mdts;
1181 std::vector<const Muon::MuonClusterOnTrack*> clusters;
1184 clusters.reserve(phiClusterOnTracks.size());
1186 for (
const auto& phiClusterOnTrack : phiClusterOnTracks) { clusters.push_back(phiClusterOnTrack->clone()); }
1190 MuonHough::HitVec::const_iterator hit = maximum.
hits.begin();
1191 MuonHough::HitVec::const_iterator hit_end = maximum.
hits.end();
1192 for (; hit != hit_end; ++hit) {
1193 ATH_MSG_DEBUG(
"hit x,y_min,y_max,w = " << (*hit)->x <<
"," << (*hit)->ymin <<
"," << (*hit)->ymax <<
"," << (*hit)->w);
1196 for (
const auto& prd : (*hit)->tgc->etaCluster) handleCluster(*prd, clusters);
1197 }
else if ((*hit)->prd) {
1215 if (mdts.size() > 2) {
1218 segmentMaker->find(
intersection.trackParameters->position(),
intersection.trackParameters->momentum(), mdts, clusters,
1219 !clusters.empty(), segColl.get(),
intersection.trackParameters->momentum().mag(), 0, beta);
1223 for (; sit != sit_end; ++sit) {
1228 segments.push_back(std::shared_ptr<const Muon::MuonSegment>(mseg));
1233 for (
const auto* hit : mdts)
delete hit;
1234 for (
const auto* hit : clusters)
delete hit;
1241 std::map<Identifier, std::vector<const Muon::RpcPrepData*>> rpcPrdsPerChamber;
1248 rpcPrdsPerChamber[chamberId].push_back(rpcPrd);
1253 MuonHough::HitVec::const_iterator hit = maximum.
hits.begin();
1254 MuonHough::HitVec::const_iterator hit_end = maximum.
hits.end();
1255 for (; hit != hit_end; ++hit) {
1256 if ((*hit)->tgc || !(*hit)->prd || !
m_idHelperSvc->isRpc((*hit)->prd->identify()))
continue;
1257 addRpc((*hit)->prd);
1261 for (
const auto& rot : maximumData.
phiClusterOnTracks) { addRpc(rot->prepRawData()); }
1264 if (rpcPrdsPerChamber.empty())
return;
1266 std::map<Identifier, std::vector<const Muon::RpcPrepData*>>
::iterator chit = rpcPrdsPerChamber.begin();
1267 std::map<Identifier, std::vector<const Muon::RpcPrepData*>>
::iterator chit_end = rpcPrdsPerChamber.end();
1268 for (; chit != chit_end; ++chit) {
1271 if (!clustering.
cluster(chit->second)) {
1277 <<
" eta clusters " << clustering.
clustersEta.size() <<
" phi clusters " << clustering.
clustersPhi.size());
1284 const std::vector<Muon::RpcClusterObj>& clusterObjects,
1287 for (
const auto& cluster : clusterObjects) {
1288 if (cluster.hitList.empty() || !cluster.hitList.front()) {
1293 << cluster.hitList.size());
1296 std::vector<const Muon::MuonClusterOnTrack*> clusters;
1297 for (
const auto* rpc : cluster.hitList) {
1300 clusters.push_back(rot);
1310 rpcTimeMeasurement.
time = result.time;
1311 rpcTimeMeasurement.
error = result.error;
1312 for (
const auto* cl : clusters) {
1314 if (rcl) rpcTimeMeasurement.
rpcClusters.push_back(std::shared_ptr<const Muon::RpcClusterOnTrack>(rcl));
1316 rpcTimeMeasurements.push_back(rpcTimeMeasurement);
1319 for (
const auto* cl : clusters)
delete cl;
1336 if (!houghDataPerSectorVec.
isValid()) {
1342 if (
static_cast<int>(houghDataPerSectorVec->vec.size()) <= sector - 1) {
1344 <<
" larger than the available sectors in the Hough tool: " << houghDataPerSectorVec->vec.size());
1353 if (houghDataPerSector.
maxVec.size() <= layHash) {
1354 ATH_MSG_WARNING(
" houghDataPerSector.maxVec.size() smaller than hash " << houghDataPerSector.
maxVec.size() <<
" hash "
1359 if (maxVec.empty())
return;
1371 float errx =
intersection.trackParameters->covariance() ?
1373 float x = barrelLike ?
z :
r;
1374 float y = barrelLike ?
r :
z;
1375 float theta = std::atan2(
y,
x);
1379 ATH_MSG_DEBUG(
" Got Phi Hough maxima " << phiMaxVec.size() <<
" phi " <<
phi);
1383 std::vector<std::shared_ptr<const Muon::MuonClusterOnTrack>>& clusters) {
1385 if (cluster) clusters.push_back(std::move(cluster));
1390 std::vector<std::shared_ptr<const Muon::MuonClusterOnTrack>> phiClusterOnTracks;
1391 Muon::MuonLayerHoughTool::PhiMaximumVec::const_iterator pit = phiMaxVec.begin();
1392 Muon::MuonLayerHoughTool::PhiMaximumVec::const_iterator pit_end = phiMaxVec.end();
1393 for (; pit != pit_end; ++pit) {
1395 for (
const std::shared_ptr<MuonHough::PhiHit>& hit : maximum.
hits) {
1398 Identifier id = hit->tgc->phiCluster.front()->identify();
1400 for (
const Muon::MuonCluster* prd : hit->tgc->phiCluster) handleCluster(*prd, phiClusterOnTracks);
1405 handleCluster(
static_cast<const Muon::MuonCluster&
>(*hit->prd), phiClusterOnTracks);
1411 <<
"," <<
y <<
") errorx " << errx <<
" "
1412 <<
" angle " <<
theta);
1415 for (
const auto& mit : maxVec) {
1417 if (std::find_if(maximum.
hits.begin(),maximum.
hits.end(),
1418 [](
const std::shared_ptr<MuonHough::Hit>& hit){
1419 return hit->prd && (hit->prd->type(Trk::PrepRawDataType::sTgcPrepData) ||
1420 hit->prd->type(Trk::PrepRawDataType::MMPrepData));
1421 }) != maximum.
hits.end())
continue;
1422 float residual = maximum.
pos -
x;
1430 const float pullUncert = std::sqrt(errx * errx + maxwidth * maxwidth / 12.);
1431 float pull = residual / (pullUncert > std::numeric_limits<float>::epsilon() ? pullUncert : 1.) ;
1433 ATH_MSG_DEBUG(
" Hough maximum " << maximum.
max <<
" position (" << refPos <<
"," << maximum.
pos <<
") residual " << residual
1434 <<
" pull " << pull <<
" angle " << maximum.
theta <<
" residual " << residualTheta);
1439 if (std::abs(pull) > 5)
continue;
1457 return std::abs(beta) > 0 ? dist * inverseSpeedOfLight / beta : 1.e12;
1462 return time != 0. ? dist * inverseSpeedOfLight / time : 20.;
1466 if (Gaudi::Concurrency::ConcurrencyFlags::numThreads() > 1) {
1467 ATH_MSG_WARNING(
"You are calling the non thread-safe MuonRecoValidationTool with multiple threads, will most likely crash");
1472 for (
const auto& candidate : candidates) {
1475 float chi2ndof = -1.;
1476 if (candidate->finalBetaFitResult.status != 0) {
1477 ntimes = candidate->stauHits.size();
1478 beta = candidate->finalBetaFitResult.beta;
1479 chi2ndof = candidate->finalBetaFitResult.chi2PerDOF();
1480 }
else if (candidate->betaFitResult.status != 0) {
1481 ntimes = candidate->hits.size();
1482 beta = candidate->betaFitResult.beta;
1483 chi2ndof = candidate->betaFitResult.chi2PerDOF();
1486 beta = candidate->betaSeed.beta;
1489 if (candidate->combinedTrack)
ATH_MSG_DEBUG(
"candidate has combined track");
1490 m_recoValidationTool->addMuonCandidate(indetTrackParticle, candidate->muonCandidate.get(), candidate->combinedTrack.get(),
1491 ntimes, beta, chi2ndof, stage);
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Helper class to provide constant type-safe access to aux data.
char data[hepevt_bytes_allocation_ATLAS]
DataVector< MuonCombined::InDetCandidate > InDetCandidateCollection
This typedef represents a collection of InDetCandidate objects.
std::pair< std::vector< unsigned int >, bool > res
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
bool msgLvl(const MSG::Level lvl) const
DataModel_detail::const_iterator< DataVector > const_iterator
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DataModel_detail::iterator< DataVector > iterator
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
ElementLink implementation for ROOT usage.
bool isValid() const
Check if the element can be found.
void addEntry(const InDetCandidate *idcand, TagBase *tag)
bool isSiliconAssociated() const
Returns true if this candidate was formed from a special far forward InDet track.
const xAOD::TrackParticle & indetTrackParticle() const
access TrackParticle
const Muon::MuonSystemExtension * getExtension() const
TagBase implementation for a combined fit.
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
virtual Amg::Transform3D GlobalToAmdbLRSTransform() 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 .
Class to represent the calibrated clusters created from CSC strips.
virtual const CscPrepData * prepRawData() const override final
Returns the CscPrepData - is a CscPrepData in this scope.
double time() const
Returns the time.
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
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 MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
Class to represent measurements from the Monitored Drift Tubes.
int adc() const
Returns the ADC (typically range is 0 to 250).
Base class for Muon cluster RIO_OnTracks.
Class representing clusters in the muon system.
void setStrategy(Strategy)
Select the strategy to be used - only one can be set at a time.
void setParameter(CreationParameter, bool value)
@ Segment
Treating a segment or a track.
This is the common class for 3D segments used in the muon spectrometer.
virtual const Amg::Vector3D & globalPosition() const override final
global position
Tracking class to hold the extrapolation from a particle from the calo entry to the end of muon syste...
const std::vector< Intersection > & layerIntersections() const
access to the intersections with the layers.
Class to represent calibrated clusters formed from RPC strips.
float time() const
Return the time (ns).
Class to represent RPC measurements.
std::vector< Hit > HitVec
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
class representing a drift circle meaurement on segment
void residual(double res)
set residual
void errorTrack(double error)
set track error
virtual bool fit(Segment &result, const Line &line, const DCOnTrackVec &dcs, double t0Seed=-99999.) const
This class represents a drift time measurement.
unsigned int index() const
double r() const
access to drift radius
const LocVec2D & position() const
access to local position
double dr() const
access to error drift radius
@ InTime
drift time too small to be compatible with drift spectrum
Implementation of 2 dimensional vector class.
void setMaxDropDepth(int max)
bool dropHits(Segment &segment, bool &hasDroppedHit, unsigned int &dropDepth) const
void setDeltaCut(double cut)
void debugLevel(int debugLevel)
void setChi2DropCut(double chi2)
void hitsOnTrack(unsigned int hitsOnTrack)
const Line & line() const
const DCOnTrackVec & dcs() const
unsigned int ndof() const
represents the three-dimensional global direction with respect to a planar surface frame.
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.
virtual bool type(MeasurementBaseType::Type type) const =0
Interface method checking the type.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
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.
virtual Intersection straightLineIntersection(const Amg::Vector3D &pos, const Amg::Vector3D &dir, bool forceDir, Trk::BoundaryCheck bchk) const override final
fast straight line intersection schema - standard: provides closest intersection and (signed) path le...
void globalToLocalDirection(const Amg::Vector3D &glodir, Trk::LocalDirection &locdir) const
This method transforms the global direction to a local direction wrt the plane.
Identifier identify() const
return the identifier
Identifier identify() const
return the identifier -extends MeasurementBase
Base class for all TrackSegment implementations, extends the common MeasurementBase.
float errorTime() const
access to the error on the measured time
float time() const
access to the measured time
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specified for StraightLineSurface: LocalToGlobal method without dynamic memory allocation.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
const Trk::Track * track() const
Returns a pointer (which can be NULL) to the Trk::Track which was used to make this TrackParticle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .).
virtual double pt() const override final
The transverse momentum ( ) of the particle.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
const std::string selection
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 ...
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
The MuonTagToSegMap is an auxillary construct that links the MuonSegments associated with a combined ...
std::string printIntersectionToString(const Muon::MuonSystemExtension::Intersection &intersection)
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
DetectorRegionIndex
enum to classify the different layers in the muon spectrometer
constexpr int toInt(const EnumType enumVal)
unsigned int sectorLayerHash(DetectorRegionIndex detectorRegionIndex, LayerIndex layerIndex)
create a hash out of region and layer
LayerIndex
enum to classify the different layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
const std::string & chName(ChIndex index)
convert ChIndex into a string
const std::string & regionName(DetectorRegionIndex index)
convert DetectorRegionIndex into a string
ChIndex
enum to classify the different chamber layers in the muon spectrometer
std::bitset< 23 > MuonDriftCircleErrorStrategyInput
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
std::vector< bool > HitSelection
std::vector< DCOnTrack > DCOnTrackVec
DataVector< const Trk::TrackStateOnSurface > TrackStates
DataVector< Trk::Segment > SegmentCollection
ParametersBase< TrackParametersDim, Charged > TrackParameters
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
const Muon::MdtPrepDataContainer * mdtPrds
struct representing the maximum in the hough space
const MuonLayerHough * hough
RegionDescriptor m_descriptor
RegionPhiMaximumVec phiMaxVec
std::vector< RpcClusterObj > clustersEta
bool cluster(const std::vector< const RpcPrepData * > &col)
std::vector< RpcClusterObj > clustersPhi
simple struct holding the fit result
float chi2PerDOF() const
chi2/ndof, return 0 if ndof == 0 or status == 0
float beta
status flag (0 = failed, 1 = ok)
simple struct holding the input to the fit