29 using namespace MuonStationIndex;
42 declareInterface<IMuonRefitTool>(
this);
132 return StatusCode::SUCCESS;
142 <<
"Failed Refit " << scaleRefit *
m_failedRefit << std::endl
144 return StatusCode::SUCCESS;
151 std::unique_ptr<Trk::Track> newTrack;
158 return std::make_unique<Trk::Track>(
track);
163 newTrack.swap(cleanedTrack);
165 newTrack = std::make_unique<Trk::Track>(
track);
169 std::unique_ptr<Trk::Track> updateErrorTrack =
171 if (!updateErrorTrack) {
176 newTrack.swap(updateErrorTrack);
179 if (settings.
refit) {
184 std::unique_ptr<Trk::Track> refittedTrack;
185 if (
track.fitQuality() &&
track.fitQuality()->chiSquared() < 10000 *
track.fitQuality()->numberDoF())
187 if (!refittedTrack) {
191 return std::make_unique<Trk::Track>(
track);
195 newTrack.swap(refittedTrack);
200 if (!extrapolatedTrack) {
206 newTrack.swap(extrapolatedTrack);
212 std::vector<std::unique_ptr<Trk::Track>>
MuonRefitTool::refit(
const std::vector<Trk::Track*>& tracks,
const EventContext& ctx,
214 std::vector<std::unique_ptr<Trk::Track>> refittedTracks;
215 refittedTracks.reserve(tracks.size());
218 return refittedTracks;
229 return updatedAEOTsTrack;
240 std::map<std::vector<Identifier>, std::pair<double, double>> alignerrmap;
242 std::vector<Trk::AlignmentDeviation*> align_deviations;
246 bool isSmallChamber =
false;
247 bool isLargeChamber =
false;
248 bool isEndcap =
false;
250 std::vector<int> usedRotations;
254 double angleError = 0.;
255 double translationError = 0.;
256 bool differentChambers =
false;
258 isSmallChamber =
false;
259 isLargeChamber =
false;
264 translationError = std::sqrt(
it->getCovariance(0, 0));
266 std::vector<Identifier> hitids;
267 const auto& vec_riowithdev =
it->getListOfHits();
270 const Identifier id_riowithdev = riowithdev->identify();
277 isSmallChamber =
true;
279 isLargeChamber =
true;
281 hitids.push_back(id_riowithdev);
283 differentChambers =
true;
284 jdifferent = hitids.size() - 1;
287 bool matchFound =
false;
288 if (!hitids.empty()) {
293 if (itRot->hasValidHashOfHits() &&
it->hasValidHashOfHits()) {
294 if (itRot->getHashOfHits() ==
it->getHashOfHits()) {
295 angleError = std::sqrt(itRot->getCovariance(0, 0));
297 usedRotations.push_back(iRot);
300 ATH_MSG_ERROR(
"One of the alignment deviations has an invalid hash created from the hits.");
303 if (matchFound)
break;
310 alignerrmap.insert(std::pair<std::vector<Identifier>, std::pair<double, double>>(
311 hitids, std::pair<double, double>(translationError, angleError)));
314 ATH_MSG_DEBUG(
" AlignmentMap entry " << iok <<
" filled with nr hitids " << hitids.size() <<
" "
315 <<
m_idHelperSvc->toString(hitids[0]) <<
" translationError " << translationError
316 <<
" angleError " << angleError);
318 ATH_MSG_DEBUG(
" AlignmentMap entry No angleError" << iok <<
" filled with nr hitids " << hitids.size() <<
" "
319 <<
m_idHelperSvc->toString(hitids[0]) <<
" translationError "
320 << translationError <<
" angleError " << angleError);
321 if (isEndcap)
ATH_MSG_DEBUG(
" AlignmentMap Endcap Chamber ");
323 if (isSmallChamber)
ATH_MSG_DEBUG(
" AlignmentMap Small Chamber ");
324 if (isLargeChamber)
ATH_MSG_DEBUG(
" AlignmentMap Large Chamber ");
325 if (differentChambers)
326 ATH_MSG_DEBUG(
" AlignmentMap entry " << iok <<
" for different Chamber "
336 isSmallChamber =
false;
337 isLargeChamber =
false;
341 bool used =
std::find(usedRotations.begin(), usedRotations.end(), iRot) != usedRotations.end();
343 ATH_MSG_ERROR(
"This following code should not be reached anymore!");
344 const auto& vec_riowithdev = itRot->getListOfHits();
346 std::vector<Identifier> hitids;
349 Identifier id_riowithdev = riowithdev->identify();
356 isSmallChamber =
true;
358 isLargeChamber =
true;
360 hitids.push_back(id_riowithdev);
363 double translationError = 0.;
364 double angleError = std::sqrt(itRot->getCovariance(0, 0));
367 alignerrmap.insert(std::pair<std::vector<Identifier>, std::pair<double, double>>(
368 hitids, std::pair<double, double>(translationError, angleError)));
369 ATH_MSG_DEBUG(
" AlignmentMap entry No Translation Error " << iok <<
" filled with nr hitids " << hitids.size() <<
" "
370 <<
m_idHelperSvc->toString(hitids[0]) <<
" translationError "
371 << translationError <<
" angleError " << angleError);
374 if (isSmallChamber)
ATH_MSG_DEBUG(
" AlignmentMap Small Chamber ");
375 if (isLargeChamber)
ATH_MSG_DEBUG(
" AlignmentMap Large Chamber ");
380 for (
auto*
it : align_deviations)
delete it;
381 align_deviations.clear();
389 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern(0);
392 std::vector<int> indexAEOTs;
393 std::vector<std::unique_ptr<Trk::TrackStateOnSurface>> tsosAEOTs;
397 std::set<ChIndex> stationIds;
399 for (
const auto& itAli : alignerrmap) {
400 unsigned int imiddle = (itAli.first.size()) / 2;
407 if (!meas) {
continue; }
409 if (!
id.is_valid())
continue;
415 if (idMiddle ==
id) {
417 const double deltaError =
std::max(itAli.second.first, 0.01);
418 const double angleError =
std::max(itAli.second.second, 0.000001);
419 auto aEOT = std::make_unique<Trk::AlignmentEffectsOnTrack>(
425 tsit->measurementOnTrack()->associatedSurface());
426 std::unique_ptr<Trk::TrackStateOnSurface> tsosAEOT =
427 std::make_unique<Trk::TrackStateOnSurface>(
429 tsit->trackParameters()->uniqueClone(),
433 indexAEOTs.push_back(
index);
434 tsosAEOTs.emplace_back(std::move(tsosAEOT));
439 if (!
found)
ATH_MSG_WARNING(
" This should not happen Identifier from AlignmentErrorTool is not found");
445 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
446 trackStateOnSurfaces->reserve(
states->size() + indexAEOTs.size());
450 for (
unsigned int i = 0;
i < indexAEOTs.size();
i++) {
451 if (
index == indexAEOTs[
i]) {
453 trackStateOnSurfaces->push_back(std::move(tsosAEOTs[
i]));
455 ATH_MSG_WARNING(
"There's a trial to push back the same AEOT twice to the track...");
461 if (tsit->alignmentEffectsOnTrack()) {
465 trackStateOnSurfaces->push_back(tsit->clone());
468 if (indexAEOTs.empty() && stationIds.size() > 1)
ATH_MSG_WARNING(
" Track without AEOT ");
470 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
471 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
491 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
492 trackStateOnSurfaces->reserve(
states->size() + 1);
496 std::vector<const Trk::TrackStateOnSurface*> indicesOfAffectedTSOS;
497 std::vector<const Trk::TrackStateOnSurface*> indicesOfAffectedTSOSInner;
498 std::vector<Identifier> indicesOfAffectedIds;
499 std::vector<Identifier> indicesOfAffectedIdsInner;
500 int index {-1}, indexFirst {-1}, indexFirstInner {-1};
510 if (!meas) {
continue; }
514 if (tsit->alignmentEffectsOnTrack()) {
515 ATH_MSG_WARNING(
" AlignmentEffectOnTrack is already on track skip it");
529 if (indexFirst == -1) indexFirst =
index;
530 indicesOfAffectedTSOS.push_back(tsit);
531 indicesOfAffectedIds.push_back(
id);
536 if (indexFirst == -1) indexFirst =
index;
537 indicesOfAffectedTSOS.push_back(tsit);
538 indicesOfAffectedIds.push_back(
id);
541 if (indexFirstInner == -1) indexFirstInner =
index;
542 indicesOfAffectedTSOSInner.push_back(tsit);
543 indicesOfAffectedIdsInner.push_back(
id);
546 if (indexFirstInner == -1) indexFirstInner =
index;
547 indicesOfAffectedTSOSInner.push_back(tsit);
548 indicesOfAffectedIdsInner.push_back(
id);
553 if (indicesOfAffectedTSOS.empty() && indicesOfAffectedTSOSInner.empty()) {
554 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
555 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
559 std::bitset<Trk::TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> typePattern(0);
562 std::unique_ptr<Trk::TrackStateOnSurface> tsosAEOT;
564 int middle = indicesOfAffectedTSOS.size() / 2;
566 auto aEOT = std::make_unique<Trk::AlignmentEffectsOnTrack>(
571 indicesOfAffectedIds,
574 << aEOT->associatedSurface()
575 <<
" nr of tsos affected "
576 << indicesOfAffectedTSOS.size());
577 tsosAEOT = std::make_unique<Trk::TrackStateOnSurface>(
585 std::unique_ptr<Trk::TrackStateOnSurface> tsosAEOTInner;
587 int middle = indicesOfAffectedTSOSInner.size() / 2;
589 auto aEOTInner = std::make_unique<Trk::AlignmentEffectsOnTrack>(
594 indicesOfAffectedIdsInner,
596 tsosAEOTInner = std::make_unique<Trk::TrackStateOnSurface>(
601 std::move(aEOTInner));
604 auto trackStateOnSurfacesAEOT = std::make_unique<Trk::TrackStates>();
605 trackStateOnSurfacesAEOT->reserve(
states->size() + 2);
609 if (
index == indexFirst && tsosAEOT) {
610 trackStateOnSurfacesAEOT->push_back(std::move(tsosAEOT));
611 if (!
m_addAll)
ATH_MSG_DEBUG(
" AlignmentEffectsOnTrack for Middle added to trackStateOnSurfacesAEOT ");
612 if (
m_addAll)
ATH_MSG_DEBUG(
" AlignmentEffectsOnTrack for All stations added to trackStateOnSurfacesAEOT ");
614 if (
index == indexFirstInner && tsosAEOTInner) {
615 trackStateOnSurfacesAEOT->push_back(std::move(tsosAEOTInner));
616 ATH_MSG_DEBUG(
" AlignmentEffectsOnTrack for Inner added to trackStateOnSurfacesAEOT ");
617 if (
m_addTwo)
ATH_MSG_DEBUG(
" also AlignmentEffectsOnTrack for Middle added to trackStateOnSurfacesAEOT ");
619 trackStateOnSurfacesAEOT->push_back(tsit);
621 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfacesAEOT),
622 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
640 std::vector<std::unique_ptr<Trk::TrackStateOnSurface>> newStates;
641 newStates.reserve(
states->size() + 5);
644 std::map<int, std::set<StIndex>> stationsPerSector;
666 if (!meas) {
continue; }
677 stationsPerSector[sector].insert(stIndex);
681 if (!
track.trackParameters() ||
track.trackParameters()->empty()) {
685 startPars =
track.trackParameters()->front();
690 std::vector<int> sectorsWithMostStations;
691 unsigned int nmaxStations = 0;
692 std::map<int, std::set<StIndex>>
::iterator stit = stationsPerSector.begin();
693 std::map<int, std::set<StIndex>>
::iterator stit_end = stationsPerSector.end();
694 for (; stit != stit_end; ++stit) {
701 if (stit->second.size() > nmaxStations) {
702 nmaxStations = stit->second.size();
703 sectorsWithMostStations.clear();
704 sectorsWithMostStations.push_back(stit->first);
705 }
else if (stit->second.size() == nmaxStations) {
706 sectorsWithMostStations.push_back(stit->first);
709 int selectedSector = -1;
710 if (sectorsWithMostStations.empty()) {
712 }
else if (sectorsWithMostStations.size() == 1) {
713 selectedSector = sectorsWithMostStations.front();
715 ATH_MSG_DEBUG(
"Found track with special sector configuration " << sectorsWithMostStations.size() <<
" ch per sector "
716 << nmaxStations <<
" using first sector");
717 selectedSector = sectorsWithMostStations.front();
718 if (selectedSector % 2 == 1 && sectorsWithMostStations.back() % 2 != 1) {
719 ATH_MSG_DEBUG(
"Revising sector choice, picking small sector ");
720 selectedSector = sectorsWithMostStations.back();
728 const std::set<StIndex>& selected_set = stationsPerSector[selectedSector];
729 const int nbarrel =
std::accumulate(barel_stations.begin(),barel_stations.end(),0, [&selected_set](
int n,
const StIndex&
idx){
730 return (selected_set.count(idx) > 0) + n;
732 const int nendcap =
std::accumulate(endcap_stations.begin(),endcap_stations.end(),0, [&selected_set](
int n,
const StIndex&
idx){
733 return (selected_set.count(idx) > 0) + n;
735 bool barrelEndcap {
false}, deweightBarrel{
false}, deweightEndcap{
false};
736 if (nbarrel > 0 && nendcap > 0) {
737 if (nbarrel < nendcap)
738 deweightBarrel =
true;
740 deweightEndcap =
true;
744 ATH_MSG_DEBUG(
" Selected sector " << selectedSector <<
" nstations " << nmaxStations <<
" barrel " << nbarrel <<
" endcap "
753 unsigned int deweightHits = 0;
754 unsigned int removedSectorHits = 0;
755 bool addedPerigee =
false;
764 newStates.emplace_back(tsos->clone());
774 if (
pars == startPars) {
788 newStates.emplace_back(tsos->clone());
794 double sign =
pars->position().dot(
pars->momentum()) > 0 ? 1. : -1.;
798 double phi =
pars->momentum().phi();
799 double theta =
pars->momentum().theta();
800 double qoverp =
pars->charge() /
pars->momentum().mag();
802 std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
805 ATH_MSG_DEBUG(
"Adding perigee in front of first measurement");
812 newStates.emplace_back(tsos->clone());
817 newStates.emplace_back(tsos->clone());
824 ATH_MSG_WARNING(
" Measurement with MDT identifier that is not a MdtDriftCircleOnTrack ");
828 bool hasT0Fit =
false;
831 std::unique_ptr<MdtDriftCircleOnTrack> rot{};
846 }
else if (deweightBarrel &&
847 std::find(barel_stations.begin(),barel_stations.end(),stIndex) != barel_stations.end()) {
851 }
else if (deweightEndcap &&
852 std::find(endcap_stations.begin(), endcap_stations.end(), stIndex) != endcap_stations.end()) {
894 rot.reset(mdt->
clone());
898 if (sector != selectedSector) {
909 <<
" radius " << rot->driftRadius() <<
" new err "
917 if (std::abs(rot->driftRadius() - mdt->
driftRadius()) > 0.1)
922 newStates.emplace_back(std::move(new_tsos));
926 newStates.emplace_back(std::move(new_tsos));
929 newStates.emplace_back(tsos->clone());
935 newStates.emplace_back(std::move(new_tsos));
938 newStates.emplace_back(tsos->clone());
943 newStates.emplace_back(tsos->clone());
946 newStates.emplace_back(tsos->clone());
950 newStates.emplace_back(tsos->clone());
958 if (deweightHits > 0)
ATH_MSG_DEBUG(
" de-weighted " << deweightHits <<
" MDT hits from neighbouring sectors");
959 if (removedSectorHits > 0)
ATH_MSG_DEBUG(
" removed " << removedSectorHits <<
" MDT hits from neighbouring sectors");
961 ATH_MSG_VERBOSE(
" original track had " <<
states->size() <<
" TSOS, adding " << newStates.size() -
states->size() <<
" new TSOS ");
964 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
965 trackStateOnSurfaces->reserve(newStates.size());
966 for (std::unique_ptr<Trk::TrackStateOnSurface>& new_state : newStates) {
967 trackStateOnSurfaces->push_back(std::move(new_state));
969 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
970 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
989 std::vector<std::unique_ptr<Trk::TrackStateOnSurface>> newStates;
990 newStates.reserve(
states->size() + 5);
1013 if (!meas) {
continue; }
1025 if (!
track.trackParameters() ||
track.trackParameters()->empty()) {
1029 startPars =
track.trackParameters()->front();
1033 bool addedPerigee =
false;
1036 if (!tsos)
continue;
1042 newStates.emplace_back(tsos->clone());
1053 if (
pars == startPars) {
1057 addedPerigee =
true;
1067 newStates.emplace_back(tsos->clone());
1073 double sign =
pars->position().dot(
pars->momentum()) > 0 ? 1. : -1.;
1077 double phi =
pars->momentum().phi();
1078 double theta =
pars->momentum().theta();
1079 double qoverp =
pars->charge() /
pars->momentum().mag();
1081 std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
1083 addedPerigee =
true;
1084 ATH_MSG_DEBUG(
"Adding perigee in front of first measurement");
1091 newStates.emplace_back(tsos->clone());
1096 newStates.emplace_back(tsos->clone());
1103 ATH_MSG_WARNING(
" Measurement with MDT identifier that is not a MdtDriftCircleOnTrack ");
1107 bool hasT0Fit =
false;
1125 newMdt = mdt->
clone();
1145 std::unique_ptr<MdtDriftCircleOnTrack> newUniqueMdt {newMdt};
1147 newStates.emplace_back(std::move(new_tsos));
1151 newStates.emplace_back(std::move(new_tsos));
1154 newStates.emplace_back(tsos->clone());
1160 newStates.emplace_back(std::move(new_tsos));
1163 newStates.emplace_back(tsos->clone());
1168 newStates.emplace_back(tsos->clone());
1171 newStates.emplace_back(tsos->clone());
1175 newStates.emplace_back(tsos->clone());
1183 ATH_MSG_VERBOSE(
" original track had " <<
states->size() <<
" TSOS, adding " << newStates.size() -
states->size() <<
" new TSOS ");
1186 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1187 trackStateOnSurfaces->reserve(newStates.size());
1188 for ( std::unique_ptr<Trk::TrackStateOnSurface>& state : newStates) {
1190 trackStateOnSurfaces->push_back(std::move(state));
1192 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
1193 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
1206 std::set<Identifier> removedIdentifiers;
1207 std::vector<const MdtDriftCircleOnTrack*> mdts;
1213 for (; tsit != tsit_end; ++tsit) {
1214 if (!*tsit)
continue;
1218 if (!
pars) {
continue; }
1224 if (!meas) {
continue; }
1229 if (!
id.is_valid()) {
continue; }
1234 ATH_MSG_WARNING(
" Measurement with MDT identifier that is not a MdtDriftCircleOnTrack ");
1241 if (chId != currentMdtChId) {
1246 if (mdts.size() > 4)
1248 <<
" hits " << mdts.size());
1255 currentMdtChId = chId;
1258 mdts.push_back(mdt);
1265 if (mdts.size() > 4)
1272 if (removedIdentifiers.empty()) {
1274 return std::make_unique<Trk::Track>(
track);
1278 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
1279 trackStateOnSurfaces->reserve(
states->size());
1281 ATH_MSG_DEBUG(
"Removing nhits: " << removedIdentifiers.size());
1284 if (!*tsit)
continue;
1291 if (removedIdentifiers.count(
id)) {
1293 trackStateOnSurfaces->push_back(std::move(new_tsos));
1297 trackStateOnSurfaces->push_back(tsos->clone());
1300 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(
track.info(), std::move(trackStateOnSurfaces),
1301 track.fitQuality() ?
track.fitQuality()->uniqueClone() :
nullptr);
1307 if (
hits.size() < 3) {
1335 detEl = mdt->prepRawData()->detectorElement();
1343 Amg::Vector3D locPos = gToStation * mdt->prepRawData()->globalPosition();
1346 double r = std::abs(mdt->localParameters()[
Trk::locR]);
1357 dcsOnTrack.emplace_back(dc, 1., 1.);
1358 dcs.emplace_back(std::move(dc));
1361 if (!detEl)
return false;
1367 surfaceTransform.pretranslate(
pars.position());
1368 double surfDim = 500.;
1369 const std::unique_ptr<Trk::PlaneSurface> surf = std::make_unique<Trk::PlaneSurface>(surfaceTransform, surfDim, surfDim);
1372 if (
dir.y() *
pars.position().y() < 0.) {
dir *= -1.; }
1377 double track_angleYZ = std::atan2(locDirTrack.z(), locDirTrack.y());
1381 double chamber_angleYZ = std::atan2(dirCh.z(), dirCh.y());
1382 double angleYZ =
locDir.angleYZ();
1389 ATH_MSG_DEBUG(
"Seeding angles " << track_angleYZ <<
" from surf " << angleYZ <<
" ch angle " << chamber_angleYZ <<
" pos "
1391 segFinder.
setPhiRoad(track_angleYZ, chamber_angleYZ, 0.14);
1395 if (dcslFitter.
fit(
segment, segPars, dcsOnTrack)) {
1396 segment.hitsOnTrack(dcsOnTrack.size());
1406 if (!segments.empty()) {
ATH_MSG_DEBUG(
"Found segments " << segments.size()); }
1408 if (segments.size() != 1) {
1409 if (
hits.size() > 3)
1413 double dthetaBest = 10000.;
1418 for (; sit != sit_end; ++sit, ++
index) {
1419 double dtheta = std::abs(sit->line().phi() - track_angleYZ);
1420 if (dtheta < dthetaBest) {
1421 dthetaBest = dtheta;
1424 if (sit->hitsOnTrack() > 4) {
ATH_MSG_DEBUG(
"Recoverable segment " << *sit); }
1426 if (indexBest != -1) {
1428 selectedSegments.push_back(segments[indexBest]);
1429 segments = selectedSegments;
1442 if (dcs.size() ==
segment.hitsOnTrack()) {
1445 }
else if (dcs.size() >
segment.hitsOnTrack() + 1) {
1447 if (
segment.hitsOnTrack() < 4)
return false;
1459 if (std::abs(dcit->r()) - std::abs(dcit->rot()->driftRadius()) > 0.1) {
1460 ATH_MSG_DEBUG(
"Large change in drift radius: r_old " << dcit->rot()->driftRadius() <<
" r_new " << dcit->r());
1464 removedIdentifiers.insert(dcit->rot()->identify());
1470 std::unique_ptr<Trk::Perigee>
1472 std::unique_ptr<Trk::Perigee> perigee;
1475 std::unique_ptr<Trk::TrackParameters> exPars{
m_muonExtrapolator->extrapolateDirectly(ctx,
pars, persurf)};
1476 perigee.reset (
dynamic_cast<Trk::Perigee*
>(exPars.release()));
1478 ATH_MSG_WARNING(
" Extrapolation to Perigee surface did not return a perigee!! ");