22   declareInterface<MuSAVtxFitterTool>(
this);
 
   39     return StatusCode::SUCCESS;
 
   49     auto newTrack = std::make_unique<xAOD::TrackParticle>();
 
   50     newTrack->makePrivateStore();
 
   58         newTrack->setDefiningParameters(1.e19, 1.e19, 1.e19, 1.e19, 0);
 
   63     newTrack->setDefiningParametersCovMatrix(*entryPars->covariance());
 
   72                                           const EventContext& ctx)
 const 
   77     std::vector<const xAOD::Muon*> candidateSAmuons;
 
   79         bool isSA = (
muon->muonType() == xAOD::Muon::MuonStandAlone);
 
   80         bool isCalo = (
muon->muonType() == xAOD::Muon::CaloTagged);
 
   81         bool isSegment = (
muon->muonType() == xAOD::Muon::SegmentTagged);
 
   82         bool isSiForward = (
muon->muonType() == xAOD::Muon::SiliconAssociatedForwardMuon);
 
   90             if (isCalo || isSegment || isSiForward) {
 
   91                 ATH_MSG_VERBOSE(
"Skipping non-SA, non-Combined muon type in validation mode!");
 
  104         if (MuSAMSTP->
pt() > 13000000) {
 
  105             ATH_MSG_DEBUG(
"Skipping SA muon with pT " << (MuSAMSTP->
pt() / 1000.) << 
" GeV!");
 
  113             ATH_MSG_DEBUG(
"Skipping SA muon with spectrometerFieldIntegral " << 
muon->spectrometerFieldIntegral << 
" T*m!");
 
  117         candidateSAmuons.push_back(
muon);
 
  121     if (candidateSAmuons.size() < 2) {
 
  123         return StatusCode::SUCCESS;
 
  127     std::vector<std::unique_ptr<xAOD::TrackParticle>> extrapolatedMuSATracks;
 
  128     std::map<const xAOD::TrackParticle*, const xAOD::Muon*> muonToExtrapolatedTrackMap;
 
  129     for (
const auto muon : candidateSAmuons) {
 
  131         auto extrapolatedMuSATrack = 
extrapolateMuSA(*MuSAMSTP, eventInfo, ctx);
 
  132         if (extrapolatedMuSATrack->definingParameters()[
Trk::d0] > 8000) {
 
  133             ATH_MSG_DEBUG(
"Failed to extrapolate MuSA track, skipping!");
 
  136         extrapolatedMuSATracks.push_back(std::move(extrapolatedMuSATrack));
 
  137         muonToExtrapolatedTrackMap[extrapolatedMuSATracks.back().get()] = 
muon;
 
  138         ATH_MSG_VERBOSE(
"Extrapolated MuSA track! Total extrapolated so far: " << extrapolatedMuSATracks.size());
 
  141     if (extrapolatedMuSATracks.size() < 2) {
 
  143         return StatusCode::SUCCESS;
 
  146     std::unique_ptr<Trk::IVKalState> state = 
m_vertexFitter->makeState(ctx);
 
  148     for (
unsigned int i = 0; 
i < extrapolatedMuSATracks.size(); 
i++) {
 
  149         for (
unsigned int j = 
i+1; j < extrapolatedMuSATracks.size(); j++) {
 
  151             std::vector<const xAOD::TrackParticle*> tracksToFit = {
 
  152                 extrapolatedMuSATracks[
i].get(),
 
  153                 extrapolatedMuSATracks[j].get()
 
  155             std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
 
  157                                                         MuSACandidate.
pos, MuSACandidate.
mom, 
 
  160                                                         MuSACandidate.
chi2, *state);
 
  161             if (
res.isSuccess()) {
 
  165                 auto sharedTrack1 = std::make_shared<const xAOD::TrackParticle>(*extrapolatedMuSATracks[
i]);
 
  166                 auto sharedTrack2 = std::make_shared<const xAOD::TrackParticle>(*extrapolatedMuSATracks[j]);
 
  170                     muonToExtrapolatedTrackMap[tracksToFit[0]],
 
  171                     muonToExtrapolatedTrackMap[tracksToFit[1]]
 
  173                 MuSACandidate.
minOpAng = muonToExtrapolatedTrackMap[tracksToFit[0]]->p4().DeltaR(
 
  174                                           muonToExtrapolatedTrackMap[tracksToFit[1]]->p4());
 
  175                 workVerticesContainer.emplace_back(MuSACandidate);
 
  183     return StatusCode::SUCCESS;
 
  189     for (
auto& workVertex : workVerticesContainer) {
 
  191             ATH_MSG_DEBUG(
"SA vertex chi2 too high, removing from consideration");
 
  192             workVertex.isGood = 
false; 
 
  197     workVerticesContainer.erase(std::remove_if(workVerticesContainer.begin(), workVerticesContainer.end(), 
 
  200     return StatusCode::SUCCESS;
 
  212     if (workVerticesContainer.size() < 2) {
 
  214         return StatusCode::SUCCESS;
 
  219     ATH_MSG_VERBOSE(
"Sorted vertices by chi2! Lowest chi2: " << workVerticesContainer.front().chi2 << 
" Highest chi2: " << workVerticesContainer.back().chi2);
 
  222     for (
unsigned int i = 0; 
i < workVerticesContainer.size(); 
i++) {
 
  223         auto& 
vertex = workVerticesContainer.at(
i);
 
  227         for (
unsigned int j = 
i+1; j < workVerticesContainer.size(); j++) {
 
  228             auto& otherVertex = workVerticesContainer.at(j);
 
  229             for (
const auto& 
muon : 
vertex.muonCandidates) {
 
  230                 if (
std::find(otherVertex.muonCandidates.begin(), otherVertex.muonCandidates.end(), 
muon) != otherVertex.muonCandidates.end()) {
 
  232                     ATH_MSG_VERBOSE(
"Found a vertex re-using a muon with chi2: " << otherVertex.chi2 << 
" removing from consideration!");
 
  233                     otherVertex.isGood = 
false;
 
  240     workVerticesContainer.erase(std::remove_if(workVerticesContainer.begin(), workVerticesContainer.end(), 
 
  243     return StatusCode::SUCCESS;