22 #include "TLorentzVector.h" 
   39   StatusCode VrtSecInclusive::extractIncompatibleTrackPairs( std::vector<WrkVrt>* workVerticesContainer )
 
   49     if( m_jp.FillIntermediateVertices ) {
 
   50       ATH_CHECK( evtStore()->
retrieve( twoTrksVertexContainer, 
"VrtSecInclusive_" + m_jp.all2trksVerticesContainerName + m_jp.augVerString ) );
 
   56     std::vector<const xAOD::TrackParticle*>    baseTracks;
 
   57     std::vector<const xAOD::NeutralParticle*>  dummyNeutrals;
 
   59     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Selected Tracks = "<< m_selectedTracks.size());
 
   60     if( m_jp.FillHist ) { m_hists[
"selTracksDist"]->Fill( m_selectedTracks.size() ); }
 
   64     enum recoStep { kStart, kInitVtxPosition, kImpactParamCheck, kVKalVrtFit, kChi2, kVposCut, kPatternMatch };
 
   66     const double maxR { 563. };         
 
   67     double roughD0Cut = 100.;
 
   68     double roughZ0Cut = 50.;
 
   69     if(m_jp.doDisappearingTrackVertexing){
 
   75     std::map<const xAOD::TruthVertex*, bool> matchMap;
 
   78     for( 
auto itrk = m_selectedTracks.begin(); itrk != m_selectedTracks.end(); ++itrk ) {
 
   79       for( 
auto jtrk = 
std::next(itrk); jtrk != m_selectedTracks.end(); ++jtrk ) {
 
   83         const int itrk_id = itrk - m_selectedTracks.begin();
 
   84         const int jtrk_id = jtrk - m_selectedTracks.begin();
 
   91         m_incomp.emplace_back( itrk_id, jtrk_id );
 
   93         if(m_jp.doDisappearingTrackVertexing) {
 
   98           if ( !cont_i || !cont_j ) {
 
  108             ATH_MSG_DEBUG(
"  link itrk (" << (*itrk)->index() << 
") or jtrk (" << (*jtrk)->index() << 
") is not valid");
 
  118         if( std::abs( (*itrk)->d0() ) < m_jp.twoTrkVtxFormingD0Cut && std::abs( (*jtrk)->d0() ) < m_jp.twoTrkVtxFormingD0Cut ) 
continue;
 
  121         baseTracks.emplace_back( *itrk );
 
  122         baseTracks.emplace_back( *jtrk );
 
  124         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kStart );
 
  129         std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
 
  130         StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
 
  131         if( 
sc.isFailure() ) {
 
  132           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation fails ");
 
  136         if( initVertex.perp() > maxR ) {
 
  139         if( m_jp.doDisappearingTrackVertexing && initVertex.perp() <m_jp.twoTrVrtMinRadius){
 
  142         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kInitVtxPosition );
 
  144         std::vector<double> impactParameters;
 
  145         std::vector<double> impactParErrors;
 
  147         if( !getSVImpactParameters( *itrk, initVertex, impactParameters, impactParErrors) ) 
continue;
 
  148         const auto roughD0_itrk = impactParameters.at(TrkParameter::k_d0);
 
  149         const auto roughZ0_itrk = impactParameters.at(TrkParameter::k_z0);
 
  150         if( fabs( impactParameters.at(0)) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) {
 
  154         if( !getSVImpactParameters( *jtrk, initVertex, impactParameters, impactParErrors) ) 
continue;
 
  155         const auto roughD0_jtrk = impactParameters.at(TrkParameter::k_d0);
 
  156         const auto roughZ0_jtrk = impactParameters.at(TrkParameter::k_z0);
 
  157         if( fabs( impactParameters.at(0) ) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) {
 
  160         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kImpactParamCheck );
 
  162         m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
 
  167         sc = m_fitSvc->VKalVrtFit( baseTracks,
 
  173         if( 
sc.isFailure() ) {
 
  176         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kVKalVrtFit );
 
  181         const double vPosMomAngT = ( vDist.x()*wrkvrt.
vertexMom.Px()+vDist.y()*wrkvrt.
vertexMom.Py() ) / vDist.perp() / wrkvrt.
vertexMom.Pt();
 
  187         const double dist_fromPV = vDist.norm();
 
  188         if( m_jp.FillHist ) m_hists[
"2trkVtxDistFromPV"]->Fill( dist_fromPV );
 
  190         if( m_jp.FillNtuple ) {
 
  192           m_ntupleVars->get<
unsigned int>( 
"All2TrkVrtNum" )++;
 
  193           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtMass" )   .emplace_back(wrkvrt.
vertexMom.M());
 
  194           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtPt" )     .emplace_back(wrkvrt.
vertexMom.Perp());
 
  195           m_ntupleVars->get< std::vector<int> >   ( 
"All2TrkVrtCharge" ) .emplace_back(wrkvrt.
Charge);
 
  196           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtX" )      .emplace_back(wrkvrt.
vertex.x());
 
  197           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtY" )      .emplace_back(wrkvrt.
vertex.y());
 
  198           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtZ" )      .emplace_back(wrkvrt.
vertex.z());
 
  199           m_ntupleVars->get< std::vector<double> >( 
"All2TrkVrtChiSq" )  .emplace_back(wrkvrt.
Chi2);
 
  206         if( m_jp.FillIntermediateVertices ) {
 
  210           for( 
const auto *trk: baseTracks ) {
 
  216             vertex->addTrackAtVertex( trackElementLink, 1. );
 
  232           isFakeAcc(*
vertex) = 
true;
 
  242         if( m_jp.FillNtuple ) m_ntupleVars->get< std::vector<int> >( 
"All2TrkSumBLHits" ).emplace_back( trkiBLHit + trkjBLHit );
 
  245         if( m_jp.FillHist ) m_hists[
"2trkChi2Dist"]->Fill( log10( wrkvrt.
Chi2 ) );
 
  247         if( wrkvrt.
fitQuality() > m_jp.SelVrtChi2Cut) {
 
  248           ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": failed to pass chi2 threshold." );
 
  251         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kChi2 );
 
  254         ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": attempting form vertex from ( " << itrk_id << 
", " << jtrk_id << 
" )." );
 
  255         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": candidate vertex: " 
  256                        << 
" isGood  = "            << (wrkvrt.
isGood? 
"true" : 
"false")
 
  261                        << 
", (r, z) = ("           << wrkvrt.
vertex.perp()
 
  262                        <<
", "                      << wrkvrt.
vertex.z() << 
")" );
 
  264         for( 
const auto* truthVertex : m_tracingTruthVertices ) {
 
  265           Amg::Vector3D vTruth( truthVertex->x(), truthVertex->y(), truthVertex->z() );
 
  268           const auto distance = vReco - vTruth;
 
  281             ATH_MSG_DEBUG ( 
" > " << __FUNCTION__ << 
": truth-matched candidate! : signif^2 = " << 
s2 );
 
  282             matchMap.emplace( truthVertex, 
true );
 
  286         if( m_jp.FillHist ) {
 
  287           dynamic_cast<TH2F*
>( m_hists[
"vPosDist"] )->Fill( wrkvrt.
vertex.perp(), vPos );
 
  288           dynamic_cast<TH2F*
>( m_hists[
"vPosMomAngTDist"] )->Fill( wrkvrt.
vertex.perp(), vPosMomAngT );
 
  289           m_hists[
"vPosMomAngT"] ->Fill( vPosMomAngT );
 
  290           m_hists[
"vPosMomAng3D"] ->Fill(  vPosMomAng3D );
 
  293         if( m_jp.doTwoTrSoftBtag ){
 
  294           if(dist_fromPV < m_jp.twoTrVrtMinDistFromPV ){
 
  295             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass the 2tr vertex min distance from PV cut." );
 
  299           if( vPosMomAng3D < m_jp.twoTrVrtAngleCut ){
 
  300             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass the vertex angle cut." );
 
  305         if( m_jp.doPVcompatibilityCut ) {
 
  306           if( 
cos( dphi1 ) < -0.8 && 
cos( dphi2 ) < -0.8 ) {
 
  307             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass the vPos cut. (both tracks are opposite against the vertex pos)" );
 
  310           if (m_jp.doTightPVcompatibilityCut && (
cos( dphi1 ) < -0.8 || 
cos( dphi2 ) < -0.8)){
 
  311             ATH_MSG_DEBUG(
" > "<< __FUNCTION__ << 
": failed to pass the tightened vPos cut. (at least one track is opposite against the vertex pos)" );
 
  314           if( vPosMomAngT < -0.8 ) {
 
  315             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass the vPos cut. (pos-mom directions are opposite)" );
 
  318           if( vPos < m_jp.pvCompatibilityCut ) {
 
  319             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass the vPos cut." );
 
  323         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kVposCut );
 
  326         if( m_jp.removeFakeVrt && !m_jp.removeFakeVrtLate ) {
 
  327           if( !this->passedFakeReject( wrkvrt.
vertex, (*itrk), (*jtrk) ) ) {
 
  329             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failed to pass fake rejection algorithm." );
 
  333         if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kPatternMatch );
 
  335         ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": passed fake rejection." );
 
  337         if( m_jp.FillNtuple ) {
 
  339           m_ntupleVars->get< 
unsigned int >( 
"AfFakVrtNum" )++;
 
  340           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtMass" )   .emplace_back(wrkvrt.
vertexMom.M());
 
  341           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtPt" )     .emplace_back(wrkvrt.
vertexMom.Perp());
 
  342           m_ntupleVars->get< std::vector<int> >   ( 
"AfFakVrtCharge" ) .emplace_back(wrkvrt.
Charge);
 
  343           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtX" )      .emplace_back(wrkvrt.
vertex.x());
 
  344           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtY" )      .emplace_back(wrkvrt.
vertex.y());
 
  345           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtZ" )      .emplace_back(wrkvrt.
vertex.z());
 
  346           m_ntupleVars->get< std::vector<double> >( 
"AfFakVrtChiSq" )  .emplace_back(wrkvrt.
Chi2);
 
  350         if( m_jp.FillIntermediateVertices && 
vertex ) {
 
  352           isFakeAcc(*
vertex)  = 
false;
 
  362         workVerticesContainer->emplace_back( wrkvrt );
 
  364         msg += Form(
" (%d, %d), ", itrk_id, jtrk_id );
 
  366         if( m_jp.FillHist ) {
 
  367           m_hists[
"initVertexDispD0"]->Fill( roughD0_itrk, initVertex.perp() );
 
  368           m_hists[
"initVertexDispD0"]->Fill( roughD0_jtrk, initVertex.perp() );
 
  369           m_hists[
"initVertexDispZ0"]->Fill( roughZ0_itrk, initVertex.z()    );
 
  370           m_hists[
"initVertexDispZ0"]->Fill( roughZ0_jtrk, initVertex.z()    );
 
  377     ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": compatible track pairs = " << 
msg );
 
  379     if( m_jp.FillNtuple ) m_ntupleVars->get<
unsigned int>( 
"SizeIncomp" ) = m_incomp.size();
 
  381     if( m_jp.FillHist ) {
 
  382       for( 
auto& pair: matchMap ) {
 
  383         if( pair.second ) m_hists[
"nMatchedTruths"]->Fill( 1, pair.first->perp() );
 
  387     return StatusCode::SUCCESS;
 
  392   StatusCode VrtSecInclusive::findNtrackVertices( std::vector<WrkVrt> *workVerticesContainer )
 
  395     if(m_jp.doDisappearingTrackVertexing){
 
  397       return StatusCode::SUCCESS;
 
  401     const auto compSize = m_selectedTracks.size()*(m_selectedTracks.size() - 1)/2 - m_incomp.size();
 
  402     if( m_jp.FillHist ) { m_hists[
"2trkVerticesDist"]->Fill( compSize ); }
 
  404     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": compatible track pair size   = " << compSize );
 
  405     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": incompatible track pair size = " << m_incomp.size() );
 
  408     if( not m_jp.doFastMode ) {
 
  410       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": incompatibility graph finder mode" );
 
  413       workVerticesContainer->clear();
 
  420       std::vector<long int> weit;
 
  422       for( 
auto& pair : m_incomp ) {
 
  423         weit.emplace_back( pair.first  + 1 ); 
 
  424         weit.emplace_back( pair.second + 1 ); 
 
  429       std::vector<long int> solution( m_selectedTracks.size() );
 
  432       long int nEdges = m_incomp.size();
 
  435       long int nTracks = 
static_cast<long int>( m_selectedTracks.size() );
 
  443       long int solutionSize { 0 };
 
  446       std::vector<const xAOD::TrackParticle*>    baseTracks;
 
  447       std::vector<const xAOD::NeutralParticle*>  dummyNeutrals;
 
  449       std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
 
  450       auto pgraph = std::make_unique<Trk::PGraph>();
 
  451       int iterationLimit(2000);
 
  456         pgraph->pgraphm_( weit.data(), nEdges, nTracks, solution.data(), &solutionSize, nth);
 
  458         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": Trk::pgraphm_() output: solutionSize = " << solutionSize );
 
  459         if (0 == iterationLimit--){
 
  460           ATH_MSG_WARNING(
"Iteration limit (2000) reached in VrtSecInclusive::findNtrackVertices, solution size = "<<solutionSize);
 
  463         if(solutionSize <= 0)  
break;      
 
  464         if(solutionSize == 1)  
continue;   
 
  468         std::string 
msg = 
"solution = [ ";
 
  469         for( 
int i=0; 
i< solutionSize; 
i++) {
 
  470           msg += Form( 
"%ld, ", solution[
i]-1 );
 
  483         for(
long int i = 0; 
i<solutionSize; 
i++) {
 
  485           baseTracks.emplace_back( m_selectedTracks.at(solution[
i]-1) );
 
  491         StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
 
  492         if(
sc.isFailure()) 
ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation fails ");
 
  494         m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
 
  496         sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
 
  506         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": FoundAppVrt=" << solutionSize << 
", (r, z) = " << wrkvrt.
vertex.perp() << 
", " << wrkvrt.
vertex.z()  <<  
", chi2/ndof = "  <<  wrkvrt.
fitQuality() );
 
  508         if( 
sc.isFailure() )  {
 
  511             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": VKalVrtFit failed in 2-trk solution ==> give up.");
 
  515           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": VKalVrtFit failed ==> retry...");
 
  523               if( itrk == jtrk ) 
continue;
 
  524               if( 
tmp.isGood ) 
continue;
 
  526               tmp.selectedTrackIndices.clear();
 
  527               tmp.selectedTrackIndices.emplace_back( itrk );
 
  528               tmp.selectedTrackIndices.emplace_back( jtrk );
 
  531               baseTracks.emplace_back( m_selectedTracks.at( itrk ) );
 
  532               baseTracks.emplace_back( m_selectedTracks.at( jtrk ) );
 
  537               sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
 
  538               if( 
sc.isFailure() ) 
ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation fails ");
 
  540               m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
 
  542               sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
 
  552               if( 
sc.isFailure() ) 
continue;
 
  560             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Did not find any viable vertex in all 2-trk combinations. Give up.");
 
  567             if( 
std::find( 
tmp.selectedTrackIndices.begin(), 
tmp.selectedTrackIndices.end(), itrk ) != 
tmp.selectedTrackIndices.end() ) 
continue;
 
  571             tmp.selectedTrackIndices.emplace_back( itrk );
 
  573             for( 
auto& jtrk : 
tmp.selectedTrackIndices ) { baseTracks.emplace_back( m_selectedTracks.at(jtrk) ); }
 
  578             sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
 
  579             if(
sc.isFailure()) 
ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation fails ");
 
  581             m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
 
  583             sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
 
  593             if( 
sc.isFailure() ) {
 
  601           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": VKalVrtFit succeeded; register the vertex to the list.");
 
  605           workVerticesContainer->emplace_back( wrkvrt );
 
  609           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": VKalVrtFit succeeded; register the vertex to the list.");
 
  613           workVerticesContainer->emplace_back( wrkvrt );
 
  622       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": rapid finder mode" );
 
  626         std::set<long int> tracks;
 
  629       std::vector<struct Cluster> 
clusters;
 
  631       for( 
auto& wrkvrt : *workVerticesContainer ) {
 
  633         bool foundCluster = 
false;
 
  636           if( (wrkvrt.vertex - cluster.position).norm() < 1.0 ) {
 
  637             for( 
auto& itrk : wrkvrt.selectedTrackIndices ) {
 
  638               cluster.tracks.insert( itrk );
 
  645         if( !foundCluster ) {
 
  647           c.position = wrkvrt.vertex;
 
  648           for( 
auto& itrk : wrkvrt.selectedTrackIndices ) {
 
  649             c.tracks.insert( itrk );
 
  652           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": added a new cluster" );
 
  658       std::vector<const xAOD::TrackParticle*>    baseTracks;
 
  659       std::vector<const xAOD::NeutralParticle*>  dummyNeutrals;
 
  661       workVerticesContainer->clear();
 
  665       std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
 
  676         for(
const auto& 
index: cluster.tracks) {
 
  678           baseTracks.emplace_back( m_selectedTracks.at( 
index ) );
 
  684         StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
 
  685         if(
sc.isFailure()) 
ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation fails ");
 
  687         m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
 
  689         sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
 
  699         if( 
sc.isFailure() ) {
 
  703         workVerticesContainer->emplace_back( wrkvrt );
 
  708     if (m_jp.truncateWrkVertices){
 
  709       if (workVerticesContainer->size() > m_jp.maxWrkVertices){
 
  710         m_vertexingStatus = 3;
 
  711         workVerticesContainer->resize(m_jp.maxWrkVertices); 
 
  719     ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": Remove vertices fully contained in other vertices .");
 
  720     while( workVerticesContainer->size() > 1 ) {
 
  721       size_t tmpN = workVerticesContainer->size();
 
  724       for(; iv<tmpN-1; iv++) {
 
  726         for(; jv<tmpN; jv++) {
 
  727           const auto nTCom = nTrkCommon( workVerticesContainer, {iv, jv} );
 
  729           if(      nTCom == workVerticesContainer->at(iv).selectedTrackIndices.size() ) {  workVerticesContainer->erase(workVerticesContainer->begin()+iv); 
break; }
 
  730           else if( nTCom == workVerticesContainer->at(jv).selectedTrackIndices.size() ) {  workVerticesContainer->erase(workVerticesContainer->begin()+jv); 
break; }
 
  735       if(iv==tmpN-1) 
break;  
 
  739     ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": Identify remaining 2-track vertices with very bad Chi2 and mass (b-tagging).");
 
  740     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
  742       if( TMath::Prob( wrkvrt.Chi2, wrkvrt.ndof() ) < m_jp.improveChi2ProbThreshold ) wrkvrt.isGood = 
false;
 
  743       if( wrkvrt.selectedTrackIndices.size() != 2 ) 
continue;
 
  744       if( m_jp.FillHist ) m_hists[
"NtrkChi2Dist"]->Fill( log10( wrkvrt.fitQuality() ) );
 
  747     if( m_jp.FillNtuple) m_ntupleVars->get<
unsigned int>( 
"NumInitSecVrt" ) = workVerticesContainer->size();
 
  749     return StatusCode::SUCCESS;
 
  754   StatusCode VrtSecInclusive::rearrangeTracks( std::vector<WrkVrt> *workVerticesContainer )
 
  756     if(m_jp.doDisappearingTrackVertexing){
 
  758       return StatusCode::SUCCESS;
 
  764     std::vector<long int> processedTracks;
 
  766     unsigned mergeCounter { 0 };
 
  767     unsigned brokenCounter { 0 };
 
  768     unsigned removeTrackCounter { 0 };
 
  773       long int maxSharedTrack;
 
  774       long int worstMatchingVertex;
 
  781       std::map<long int, std::vector<long int> > trackToVertexMap;
 
  784       trackClassification( workVerticesContainer, trackToVertexMap );
 
  787       auto worstChi2 = findWorstChi2ofMaximallySharedTrack( workVerticesContainer, trackToVertexMap, maxSharedTrack, worstMatchingVertex );
 
  790         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": no shared tracks are found --> exit the while loop." );
 
  794       ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": vertex [" << worstMatchingVertex << 
"]: maximally shared track index = " << maxSharedTrack
 
  795                      << 
", multiplicity = "   << trackToVertexMap.at( maxSharedTrack ).size()
 
  796                      << 
", worst chi2_trk = " << worstChi2 );
 
  799       if( worstChi2 < m_jp.TrackDetachCut ) {
 
  804         std::vector< std::pair<unsigned, unsigned> > badPairs;
 
  810           unsigned nShared { 0 };
 
  813             auto& vrtList = trackToVertexMap.at( maxSharedTrack );
 
  815             auto nGood = std::count_if( vrtList.begin(), vrtList.end(), [&]( 
auto& 
v ) { return workVerticesContainer->at(v).isGood; } );
 
  818             std::vector< std::tuple< std::pair<unsigned, unsigned>, 
double, 
unsigned> > significanceTuple;
 
  819             enum { kIndexPair, kSignificance, kNshared };
 
  821             for( 
auto ivrt = vrtList.begin(); ivrt != vrtList.end(); ++ivrt ) {
 
  822               for( 
auto jvrt = 
std::next( ivrt ); jvrt != vrtList.end(); ++jvrt ) {
 
  823                 auto pair = std::pair<unsigned, unsigned>( *ivrt, *jvrt );
 
  825                 if( !( workVerticesContainer->at(*ivrt).isGood ) ) 
continue;
 
  826                 if( !( workVerticesContainer->at(*jvrt).isGood ) ) 
continue;
 
  829                 if( 
std::find( badPairs.begin(), badPairs.end(), pair ) != badPairs.end() ) 
continue;
 
  831                 auto signif = significanceBetweenVertices( workVerticesContainer->at( *ivrt ), workVerticesContainer->at( *jvrt ) );
 
  833                 auto& ivrtTrks = workVerticesContainer->at(*ivrt).selectedTrackIndices;
 
  834                 auto& jvrtTrks = workVerticesContainer->at(*jvrt).selectedTrackIndices;
 
  836                 auto nSharedTracks = std::count_if( ivrtTrks.begin(), ivrtTrks.end(),
 
  838                                                       return std::find( jvrtTrks.begin(), jvrtTrks.end(), index ) != jvrtTrks.end();
 
  841                 significanceTuple.emplace_back( pair, signif, nSharedTracks );
 
  845             if( significanceTuple.empty() ) {
 
  846               ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": no vertex pairs are found --> exit the while loop." );
 
  850             auto minSignificanceTuple = std::min_element( significanceTuple.begin(), significanceTuple.end(), [&]( 
auto& 
t1, 
auto&
t2 ) { return std::get<kSignificance>(t1) < std::get<kSignificance>(t2); } );
 
  852             indexPair       = std::get<kIndexPair>    ( *minSignificanceTuple );
 
  853             minSignificance = std::get<kSignificance> ( *minSignificanceTuple );
 
  854             nShared         = std::get<kNshared>      ( *minSignificanceTuple );
 
  857           ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": minSignificance = " << minSignificance );
 
  859           if( minSignificance < m_jp.VertexMergeCut || nShared >= 2 ) {
 
  861             ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": attempt to merge vertices " << indexPair.first << 
" and " << indexPair.second );
 
  863             WrkVrt vertex_backup1 = workVerticesContainer->at( indexPair.first );
 
  864             WrkVrt vertex_backup2 = workVerticesContainer->at( indexPair.second );
 
  866             StatusCode sc = mergeVertices( workVerticesContainer->at( indexPair.first ), workVerticesContainer->at( indexPair.second ) );
 
  868             if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill( RECONSTRUCT_NTRK ); }
 
  870             if( 
sc.isFailure() ) {
 
  872               workVerticesContainer->at( indexPair.first  ) = vertex_backup1;
 
  873               workVerticesContainer->at( indexPair.second ) = vertex_backup2;
 
  874               badPairs.emplace_back( indexPair );
 
  879             workVerticesContainer->at( indexPair.second ).isGood = 
false;
 
  886             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Merged vertices " << indexPair.first << 
" and " << indexPair.second << 
". merged vertex multiplicity = " << workVerticesContainer->at( indexPair.first ).selectedTrackIndices.size() );
 
  894             auto& wrkvrt = workVerticesContainer->at( worstMatchingVertex );
 
  896             auto end = 
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(), [&]( 
auto& 
index ) { return index == maxSharedTrack; } );
 
  897             wrkvrt.selectedTrackIndices.erase( 
end, wrkvrt.selectedTrackIndices.end() );
 
  899             removeTrackCounter++;
 
  901             ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": removed track " << maxSharedTrack << 
" from vertex " << worstMatchingVertex );
 
  903             if( wrkvrt.selectedTrackIndices.size() < 2 ) {
 
  904               wrkvrt.isGood = 
false;
 
  910             if( 
sc.isFailure() ) {
 
  911               ATH_MSG_WARNING(
" > " << __FUNCTION__ << 
": detected vertex fitting failure!" );
 
  924         auto& wrkvrt = workVerticesContainer->at( worstMatchingVertex );
 
  926         auto end = 
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(), [&]( 
auto& 
index ) { return index == maxSharedTrack; } );
 
  927         wrkvrt.selectedTrackIndices.erase( 
end, wrkvrt.selectedTrackIndices.end() );
 
  929         if( wrkvrt.nTracksTotal() >=2 ) {
 
  931           auto wrkvrt_backup = wrkvrt;
 
  933           if( 
sc.isFailure() ) {
 
  934             ATH_MSG_WARNING(
" > " << __FUNCTION__ << 
": detected vertex fitting failure!" );
 
  935             wrkvrt = wrkvrt_backup;
 
  939           wrkvrt.isGood = 
false;
 
  943         removeTrackCounter++;
 
  945         ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": removed track " << maxSharedTrack << 
" from vertex " << worstMatchingVertex );
 
  953     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
  955       if(!wrkvrt.isGood )                          
continue;  
 
  956       if( wrkvrt.selectedTrackIndices.size() < 3 ) 
continue;
 
  959       improveVertexChi2( wrkvrt );
 
  960       if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
 
  962       if( wrkvrt.nTracksTotal() < 2 ) wrkvrt.
isGood = 
false;
 
  966     if( m_jp.FillNtuple ) {
 
  967       m_ntupleVars->get<
unsigned int>( 
"NumRearrSecVrt" )=workVerticesContainer->size();
 
  968       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Size of Solution Set: "<< m_ntupleVars->get<
unsigned int>( 
"NumRearrSecVrt" ));
 
  971     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
  972     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Number of merges = " << mergeCounter << 
", Number of track removal = " << removeTrackCounter << 
", broken vertices = " << brokenCounter );
 
  973     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
  975     return StatusCode::SUCCESS;
 
  980   StatusCode VrtSecInclusive::reassembleVertices( std::vector<WrkVrt>* workVerticesContainer )
 
  989     unsigned reassembleCounter { 0 };
 
  992     std::sort( workVerticesContainer->begin(), workVerticesContainer->end(), [](
WrkVrt& v1, 
WrkVrt& 
v2) { return v1.selectedTrackIndices.size() < v2.selectedTrackIndices.size(); } );
 
  994     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": #vertices = " << workVerticesContainer->size() );
 
  996     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
  997       if( !wrkvrt.isGood               ) 
continue;
 
  998       if(  wrkvrt.selectedTrackIndices.size() <= 1 ) 
continue;
 
 1000       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": vertex " << &wrkvrt << 
" #tracks = " << wrkvrt.selectedTrackIndices.size() );
 
 1001       ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": candidate vertex: " 
 1002                      << 
" isGood  = "            << (wrkvrt.isGood? 
"true" : 
"false")
 
 1003                      << 
", #ntrks = "            << wrkvrt.nTracksTotal()
 
 1004                      << 
", #selectedTracks = "   << wrkvrt.selectedTrackIndices.size()
 
 1005                      << 
", #associatedTracks = " << wrkvrt.associatedTrackIndices.size()
 
 1006                      << 
", chi2/ndof = "         << wrkvrt.fitQuality()
 
 1007                      << 
", (r, z) = ("           << wrkvrt.vertex.perp()
 
 1008                      <<
", "                      << wrkvrt.vertex.z() << 
")" );
 
 1010       std::map<unsigned, std::vector<WrkVrt>::reverse_iterator> mergiableVertex;
 
 1011       std::set<std::vector<WrkVrt>::reverse_iterator> mergiableVerticesSet;
 
 1013       for( 
auto& 
index : wrkvrt.selectedTrackIndices ) {
 
 1017         mergiableVertex[
index] = workVerticesContainer->rend();
 
 1019         std::vector<double> distances;
 
 1022         for( 
auto ritr = workVerticesContainer->rbegin(); ritr != workVerticesContainer->rend(); ++ritr ) {
 
 1023           auto& targetVertex = *ritr;
 
 1025           if( &wrkvrt == &targetVertex ) 
continue;
 
 1026           if( wrkvrt.selectedTrackIndices.size() >= targetVertex.selectedTrackIndices.size() ) 
continue;
 
 1029           std::vector<double> impactParameters;
 
 1030           std::vector<double> impactParErrors;
 
 1032           if( !getSVImpactParameters(trk,targetVertex.vertex,impactParameters,impactParErrors) ) 
continue;
 
 1034           const auto& 
distance = hypot( impactParameters.at(0), impactParameters.at(1) );
 
 1035           distances.emplace_back( 
distance );
 
 1037           if( std::abs( impactParameters.at(0) ) > m_jp.reassembleMaxImpactParameterD0 ) 
continue;
 
 1038           if( std::abs( impactParameters.at(1) ) > m_jp.reassembleMaxImpactParameterZ0 ) 
continue;
 
 1040           mergiableVertex[
index] = ritr;
 
 1041           mergiableVerticesSet.emplace( ritr );
 
 1045         auto min_distance = !distances.empty() ? *(std::min_element( distances.begin(), distances.end() )) : 
AlgConsts::invalidFloat;
 
 1047         if( mergiableVertex[
index] == workVerticesContainer->rend() ) {
 
 1048           ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": track " << trk << 
" --> none : min distance = " << min_distance );
 
 1050           ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": track " << trk << 
" --> " << &( *(mergiableVertex[
index]) ) << 
" --> size = " << mergiableVertex[
index]->selectedTrackIndices.size() << 
": min distance = " << min_distance );
 
 1055       size_t count_mergiable = std::count_if( mergiableVertex.begin(), mergiableVertex.end(),
 
 1056                                               [&](
const std::pair<
unsigned, std::vector<WrkVrt>::reverse_iterator>& 
p ) {
 
 1057                                                 return p.second != workVerticesContainer->rend(); } );
 
 1059       if( mergiableVerticesSet.size() == 1 && count_mergiable == wrkvrt.selectedTrackIndices.size() ) {
 
 1061         ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": identified a unique association destination vertex" );
 
 1063         WrkVrt& destination = *( mergiableVertex.begin()->second );
 
 1067         if( 
sc.isFailure() ) {
 
 1068           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": failure in vertex merging" );
 
 1071         improveVertexChi2( destination );
 
 1073         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": merged destination vertex: " 
 1074                        << 
" isGood  = "            << (destination.
isGood? 
"true" : 
"false")
 
 1078                        << 
", chi2/ndof = "         << destination.
fitQuality()
 
 1079                        << 
", (r, z) = ("           << destination.
vertex.perp()
 
 1080                        <<
", "                      << destination.
vertex.z() << 
")" );
 
 1082         if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill( REASSEMBLE ); }
 
 1086         reassembleCounter++;
 
 1092     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1093     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": reassembled vertices = " << reassembleCounter );
 
 1094     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1096     return StatusCode::SUCCESS;
 
 1101   StatusCode VrtSecInclusive::associateNonSelectedTracks( std::vector<WrkVrt>* workVerticesContainer )
 
 1110     if( !m_decor_isAssociated ) {
 
 1111       m_decor_isAssociated.emplace ( 
"is_associated" + m_jp.augVerString );
 
 1114     ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": #verticess = " << workVerticesContainer->size() );
 
 1116     unsigned associateCounter { 0 };
 
 1119     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
 1121       if( !wrkvrt.isGood               ) 
continue;
 
 1122       if(  wrkvrt.selectedTrackIndices.size() <= 1 ) 
continue;
 
 1124       improveVertexChi2( wrkvrt );
 
 1126       wrkvrt.Chi2_core = wrkvrt.Chi2;
 
 1128       auto& vertexPos = wrkvrt.vertex;
 
 1130       std::vector<double> distanceToPVs;
 
 1132       for( 
const auto* 
pv : *pvs ) {
 
 1135       const auto& minDistance = *( std::min_element( distanceToPVs.begin(), distanceToPVs.end() ) );
 
 1137       if( minDistance < m_jp.associateMinDistanceToPV ) 
continue;
 
 1140       ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": vertex pos = (" << vertexPos.x() << 
", " << vertexPos.y() << 
", " << vertexPos.z() << 
"), " 
 1141                      "#selected = " << wrkvrt.selectedTrackIndices.size() << 
", #assoc = " << wrkvrt.associatedTrackIndices.size() );
 
 1143       std::vector<const xAOD::TrackParticle*> 
candidates;
 
 1146       for( 
auto itr = allTracks->
begin(); itr != allTracks->
end(); ++itr ) {
 
 1147         const auto* trk = *itr;
 
 1151           auto result = std::find_if( workVerticesContainer->begin(), workVerticesContainer->end(),
 
 1153                                         auto found = std::find_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
 
 1154                                                                    [&]( long int index ) {
 
 1156                                                                     if (m_jp.doSelectTracksFromElectrons || m_jp.doSelectIDAndGSFTracks) {
 
 1157                                                                       const xAOD::TrackParticle *id_tr;
 
 1158                                                                       id_tr = xAOD::EgammaHelpers::getOriginalTrackParticleFromGSF(m_selectedTracks.at(index));
 
 1159                                                                       return trk == m_selectedTracks.at(index) or trk == id_tr;
 
 1162                                                                       return trk == m_selectedTracks.at(index);
 
 1167           if( 
result != workVerticesContainer->end() ) 
continue;
 
 1172           auto result = std::find_if( m_associatedTracks.begin(), m_associatedTracks.end(),
 
 1173                                       [&] (
const auto* atrk) { return trk == atrk; } );
 
 1174           if( 
result != m_associatedTracks.end() ) 
continue;
 
 1181         if( trk->pt() < m_jp.associatePtCut ) 
continue;
 
 1184         if( trk->chiSquared() / trk->numberDoF() > m_jp.associateChi2Cut ) 
continue;
 
 1187         if( !checkTrackHitPatternToVertexOuterOnly( trk, vertexPos ) ) 
continue;
 
 1190         std::vector<double> impactParameters;
 
 1191         std::vector<double> impactParErrors;
 
 1193         if( !getSVImpactParameters( trk, vertexPos, impactParameters, impactParErrors) ) 
continue;
 
 1195         if( std::abs( impactParameters.at(0) ) / sqrt( impactParErrors.at(0) ) > m_jp.associateMaxD0Signif ) 
continue;
 
 1196         if( std::abs( impactParameters.at(1) ) / sqrt( impactParErrors.at(1) ) > m_jp.associateMaxZ0Signif ) 
continue;
 
 1199                        << 
": d0 to vtx = " << impactParameters.at(k_d0)
 
 1200                        << 
", z0 to vtx = " << impactParameters.at(k_z0)
 
 1201                        << 
", distance to vtx = " << hypot( impactParameters.at(k_d0), impactParameters.at(k_z0) ) );
 
 1209       std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
 
 1213         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": attempting to associate track = " << trk );
 
 1216         WrkVrt wrkvrt_backup = wrkvrt;
 
 1218         m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
 
 1220         std::vector<const xAOD::TrackParticle*>   baseTracks;
 
 1221         std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
 
 1225         for( 
const auto& 
index : wrkvrt.selectedTrackIndices ) {
 
 1226           baseTracks.emplace_back( m_selectedTracks.at( 
index ) );
 
 1229         for( 
const auto& 
index : wrkvrt.associatedTrackIndices ) {
 
 1230           baseTracks.emplace_back( m_associatedTracks.at( 
index ) );
 
 1234         baseTracks.emplace_back( trk );
 
 1240           StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initPos, *state );
 
 1242           if( 
sc.isFailure() ) 
ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": fast crude estimation failed.");
 
 1244           const auto& diffPos = initPos - vertexPos;
 
 1246           if( diffPos.norm() > 10. ) {
 
 1248             ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": approx vertex as original" );
 
 1249             m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
 
 1253             ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": approx vertex set to (" << initPos.x() << 
", " << initPos.y() << 
", " << initPos.z() << 
")" );
 
 1254             m_fitSvc->setApproximateVertex( initPos.x(), initPos.y(), initPos.z(), *state );
 
 1260         ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": now vertex fitting..." );
 
 1262         StatusCode sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
 
 1272         if( 
sc.isFailure() ) {
 
 1273           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": VKalVrtFit failure. Revert to backup");
 
 1274           wrkvrt = wrkvrt_backup;
 
 1276           if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 1 );
 
 1282         if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 0 );
 
 1284         auto& 
cov = wrkvrt.vertexCov;
 
 1286         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": succeeded in associating. New vertex pos = (" << vertexPos.perp() << 
", " << vertexPos.z() << 
", " << vertexPos.perp()*vertexPos.phi() << 
")" );
 
 1287         ATH_MSG_VERBOSE( 
" > " << __FUNCTION__ << 
": New vertex cov = (" << 
cov.at(0) << 
", " << 
cov.at(1) << 
", " << 
cov.at(2) << 
", " << 
cov.at(3) << 
", " << 
cov.at(4) << 
", " << 
cov.at(5) << 
")" );
 
 1291         wrkvrt.associatedTrackIndices.emplace_back( m_associatedTracks.size() );
 
 1293         m_associatedTracks.emplace_back( trk );
 
 1294         (*m_decor_isAssociated)( *trk ) = 
true;
 
 1300     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1301     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": total associated number of tracks = " << associateCounter );
 
 1302     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1304     return StatusCode::SUCCESS;
 
 1309   StatusCode VrtSecInclusive::mergeByShuffling( std::vector<WrkVrt> *workVerticesContainer )
 
 1312     ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": #verticess = " << workVerticesContainer->size() );
 
 1314     unsigned mergeCounter { 0 };
 
 1317     std::sort( workVerticesContainer->begin(), workVerticesContainer->end(), [](
WrkVrt& v1, 
WrkVrt& 
v2) { return v1.selectedTrackIndices.size() < v2.selectedTrackIndices.size(); } );
 
 1320     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
 1321       if( !wrkvrt.isGood               )             
continue;
 
 1322       if(  wrkvrt.selectedTrackIndices.size() <= 1 ) 
continue;
 
 1325       for( 
auto ritr = workVerticesContainer->rbegin(); ritr != workVerticesContainer->rend(); ++ritr ) {
 
 1326         auto& vertexToMerge = *ritr;
 
 1328         if( !vertexToMerge.isGood               )                                             
continue;
 
 1329         if(  vertexToMerge.selectedTrackIndices.size() <= 1 )                                 
continue;
 
 1330         if( &wrkvrt == &vertexToMerge     )                                                   
continue;
 
 1331         if(  vertexToMerge.selectedTrackIndices.size() < wrkvrt.selectedTrackIndices.size() ) 
continue;
 
 1333         const double& significance = significanceBetweenVertices( wrkvrt, vertexToMerge );
 
 1335         if( significance > m_jp.mergeByShufflingMaxSignificance ) 
continue;
 
 1337         bool mergeFlag { 
false };
 
 1340                       << 
": vertex " << &wrkvrt << 
" #tracks = " << wrkvrt.selectedTrackIndices.size()
 
 1341                       << 
" --> to Merge : " << &vertexToMerge << 
", #tracks = " << vertexToMerge.selectedTrackIndices.size()
 
 1342                       << 
" significance = " << significance );
 
 1347         if( m_jp.doSuggestedRefitOnMerging && !mergeFlag ) {
 
 1348           WrkVrt testVertex = wrkvrt;
 
 1350           if( 
sc.isFailure() ) {
 
 1354             const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
 
 1355             if( signif < min_signif ) min_signif = signif;
 
 1357             if( signif < m_jp.mergeByShufflingAllowance ) {
 
 1358               ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
":  method1:  vertexToMerge " << &vertexToMerge << 
": test signif = " << signif );
 
 1363             if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif1"]->Fill( log10( min_signif ) );
 
 1364             if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE1 ); }
 
 1369         if( m_jp.doMagnetMerging && !mergeFlag ) {
 
 1372           for( 
auto& 
index : vertexToMerge.selectedTrackIndices ) {
 
 1374             WrkVrt testVertex = wrkvrt;
 
 1378             if( 
sc.isFailure() ) {
 
 1382               const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
 
 1383               if( signif < min_signif ) min_signif = signif;
 
 1385               if( signif < m_jp.mergeByShufflingAllowance ) {
 
 1386                 ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": method2:  vertexToMerge " << &vertexToMerge << 
" track index " << 
index << 
": test signif = " << signif );
 
 1393           if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif2"]->Fill( log10( min_signif ) );
 
 1395           if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE2 ); }
 
 1399         if( m_jp.doWildMerging && !mergeFlag ) {
 
 1401           WrkVrt testVertex = wrkvrt;
 
 1403           for( 
auto& 
index : vertexToMerge.selectedTrackIndices ) {
 
 1408           if( 
sc.isFailure() ) {
 
 1412             const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
 
 1413             if( signif < min_signif ) min_signif = signif;
 
 1415             if( signif < m_jp.mergeByShufflingAllowance ) {
 
 1416               ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": method3:  vertexToMerge " << &vertexToMerge << 
": test signif = " << signif );
 
 1420             if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif3"]->Fill( log10( min_signif ) );
 
 1421             if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE3 ); }
 
 1428           ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
":   vertexToMerge " << &vertexToMerge << 
" ==> min signif = " << min_signif << 
" judged to merge" );
 
 1430           auto vertexToMerge_backup = vertexToMerge;
 
 1431           auto wrkvrt_backup        = wrkvrt;
 
 1433           StatusCode sc = mergeVertices( vertexToMerge, wrkvrt );
 
 1434           if( 
sc.isFailure() ) {
 
 1435             vertexToMerge = vertexToMerge_backup;
 
 1436             wrkvrt        = wrkvrt_backup;
 
 1440           improveVertexChi2( wrkvrt );
 
 1449     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1450     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Number of merges = " << mergeCounter );
 
 1451     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1453     return StatusCode::SUCCESS;
 
 1458   StatusCode VrtSecInclusive::mergeFinalVertices( std::vector<WrkVrt> *workVerticesContainer )
 
 1461     unsigned mergeCounter { 0 };
 
 1467       for( 
auto& wrkvrt : *workVerticesContainer) {
 
 1473       auto minDistance = findMinVerticesPair( workVerticesContainer, indexPair, &VrtSecInclusive::distanceBetweenVertices );
 
 1479       auto& v1 = workVerticesContainer->at(indexPair.first);
 
 1480       auto& 
v2 = workVerticesContainer->at(indexPair.second);
 
 1482       const double averageRadius = ( v1.vertex.perp() + 
v2.vertex.perp() ) / 2.0;
 
 1484       if( minDistance >  m_jp.VertexMergeFinalDistCut + m_jp.VertexMergeFinalDistScaling * averageRadius ) {
 
 1485         ATH_MSG_DEBUG( 
"Vertices " << indexPair.first << 
" and " << indexPair.second
 
 1486             <<
" are separated by distance " << minDistance );
 
 1490       ATH_MSG_DEBUG( 
"Merging FINAL vertices " << indexPair.first << 
" and " << indexPair.second
 
 1491                      <<
" which are separated by distance "<< minDistance );
 
 1494       if( 
sc.isFailure() ) {}
 
 1495       if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill( 
FINAL ); }
 
 1497       improveVertexChi2( v1 );
 
 1503     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1504     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Number of merges = " << mergeCounter );
 
 1505     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
"----------------------------------------------" );
 
 1507     return StatusCode::SUCCESS;
 
 1514   StatusCode VrtSecInclusive::refitAndSelectGoodQualityVertices( std::vector<WrkVrt> *workVerticesContainer )
 
 1524     ATH_CHECK( evtStore()->
retrieve( secondaryVertexContainer, 
"VrtSecInclusive_" + m_jp.secondaryVerticesContainerName + m_jp.augVerString ) );
 
 1529     enum { kPt, 
kEta, 
kPhi, kD0, kZ0, kErrP, kErrD0, kErrZ0, kChi2SV };
 
 1530     if( m_trkDecors.empty() ) {
 
 1541     if( !m_decor_is_svtrk_final ) {
 
 1542       m_decor_is_svtrk_final.emplace ( 
"is_svtrk_final" + m_jp.augVerString );
 
 1545     std::map<const WrkVrt*, const xAOD::Vertex*> wrkvrtLinkMap;
 
 1548     const auto& ctx = Gaudi::Hive::currentContext();
 
 1550     ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": input #vertices = " << workVerticesContainer->size() );
 
 1553     for( 
auto& wrkvrt : *workVerticesContainer ) {
 
 1555       ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": candidate vertex: " 
 1556                      << 
" isGood  = "            << (wrkvrt.isGood? 
"true" : 
"false")
 
 1557                      << 
", #ntrks = "            << wrkvrt.nTracksTotal()
 
 1558                      << 
", #selectedTracks = "   << wrkvrt.selectedTrackIndices.size()
 
 1559                      << 
", #associatedTracks = " << wrkvrt.associatedTrackIndices.size()
 
 1561                      << 
", (r, z) = ("           << wrkvrt.vertex.perp()
 
 1562                      <<
", "                      << wrkvrt.vertex.z() << 
")" );
 
 1564       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 0 );
 
 1566       if( m_jp.removeFakeVrt && m_jp.removeFakeVrtLate ) {
 
 1567         removeInconsistentTracks( wrkvrt );
 
 1570       if( wrkvrt.nTracksTotal() < 2 ) {
 
 1571         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": ntrk < 2  --> rejected." );
 
 1575       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 1 );
 
 1579       if( wrkvrt.vertex.perp() < 31.0 ) {
 
 1582         wrkvrt.selectedTrackIndices.erase( 
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
 
 1583                                                            [&]( 
auto& 
index ) {
 
 1584                                                              auto* trk = m_selectedTracks.at( index );
 
 1588                                            wrkvrt.selectedTrackIndices.end() );
 
 1591         wrkvrt.associatedTrackIndices.erase( 
std::remove_if( wrkvrt.associatedTrackIndices.begin(), wrkvrt.associatedTrackIndices.end(),
 
 1592                                                              [&]( 
auto& 
index ) {
 
 1593                                                                auto* trk = m_associatedTracks.at( index );
 
 1597                                              wrkvrt.associatedTrackIndices.end() );
 
 1605       if( m_jp.doFinalImproveChi2 ) {
 
 1609         improveVertexChi2( wrkvrt );
 
 1611         if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
 
 1616       if( wrkvrt.nTracksTotal() < 2 ) 
continue;
 
 1619       if( wrkvrt.selectedTrackIndices.size() < 2 ) 
continue;
 
 1622       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 2 );
 
 1629         if( 
sc.isFailure() ) {
 
 1631           auto indices = wrkvrt.associatedTrackIndices;
 
 1633           wrkvrt.associatedTrackIndices.clear();
 
 1634           sc = refitVertex( wrkvrt );
 
 1635           if( 
sc.isFailure() ) {
 
 1636             ATH_MSG_WARNING(
" > " << __FUNCTION__ << 
": detected vertex fitting failure!" );
 
 1639           if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
 
 1644             sc = refitVertex( wrkvrt );
 
 1645             if( 
sc.isFailure() || TMath::Prob( wrkvrt.Chi2, wrkvrt.ndof() ) < m_jp.improveChi2ProbThreshold ) {
 
 1646               ATH_MSG_WARNING(
" > " << __FUNCTION__ << 
": detected vertex fitting failure!" );
 
 1653           if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
 
 1657       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 3 );
 
 1662       if( m_jp.FillNtuple ) m_ntupleVars->get<
unsigned int>( 
"NumSecVrt" )++;
 
 1664       TLorentzVector sumP4_pion;
 
 1665       TLorentzVector sumP4_electron;
 
 1666       TLorentzVector sumP4_proton;
 
 1669       bool good_flag = 
true;
 
 1671       std::map<const std::deque<long int>*, 
const std::vector<const xAOD::TrackParticle*>&> indicesSet
 
 1673             { &(wrkvrt.selectedTrackIndices),   m_selectedTracks   },
 
 1674             { &(wrkvrt.associatedTrackIndices), m_associatedTracks }
 
 1677       for( 
auto& pair : indicesSet ) {
 
 1679         const auto* 
indices = pair.first;
 
 1680         const auto& tracks  = pair.second;
 
 1682         for( 
const auto& itrk : *
indices ) {
 
 1683           const auto* trk = tracks.at( itrk );
 
 1684           auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
 
 1686             ATH_MSG_INFO(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": Failed in obtaining the SV perigee!" );
 
 1694         ATH_MSG_DEBUG( 
" > " << __FUNCTION__ << 
": sv perigee could not be obtained --> rejected" );
 
 1698       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 4 );
 
 1701       std::vector<const xAOD::TrackParticle*> tracks;
 
 1702       std::vector< std::pair<const xAOD::TrackParticle*, double> > trackChi2Pairs;
 
 1706         for( 
auto& pair : indicesSet ) {
 
 1707           for( 
const auto& 
index : *pair.first ) tracks.emplace_back( pair.second.at( 
index ) );
 
 1710         auto trkitr = tracks.begin();
 
 1711         auto chi2itr = wrkvrt.Chi2PerTrk.begin();
 
 1713         for( ; ( trkitr!=tracks.end() && chi2itr!=wrkvrt.Chi2PerTrk.end() ); ++trkitr, ++chi2itr ) {
 
 1714           trackChi2Pairs.emplace_back( *trkitr, *chi2itr );
 
 1720       TLorentzVector sumP4_selected;
 
 1722       bool badIPflag { 
false };
 
 1725       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Track loop: size = " << tracks.size() );
 
 1726       for( 
auto& pair : trackChi2Pairs ) {
 
 1728         const auto* trk      = pair.first;
 
 1729         const auto& chi2AtSV = pair.second;
 
 1731         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": start." );
 
 1734         fillTrackSummary( trk_summary, trk );
 
 1740         double trk_pt  = trk->pt();
 
 1741         double trk_eta = trk->eta();
 
 1742         double trk_phi = trk->phi();
 
 1744         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": in vrt chg/pt/phi/eta = " 
 1745             << trk->charge() <<
"," 
 1752         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": Get the prigee of the track at the vertex." );
 
 1754         auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
 
 1756           ATH_MSG_WARNING(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": Failed in obtaining the SV perigee!" );
 
 1758           for( 
auto& pair : m_trkDecors ) {
 
 1761           (*m_decor_is_svtrk_final)( *trk ) = 
true;
 
 1765         double qOverP_wrtSV    = sv_perigee->parameters() [
Trk::qOverP];
 
 1766         double theta_wrtSV     = sv_perigee->parameters() [
Trk::theta];
 
 1767         double p_wrtSV         = 1.0 / std::abs( qOverP_wrtSV );
 
 1768         double pt_wrtSV        = p_wrtSV * 
sin( theta_wrtSV );
 
 1769         double eta_wrtSV       = -
log( 
tan( theta_wrtSV/2. ) );
 
 1770         double phi_wrtSV       = sv_perigee->parameters() [
Trk::phi];
 
 1771         double d0_wrtSV        = sv_perigee->parameters() [
Trk::d0];
 
 1772         double z0_wrtSV        = sv_perigee->parameters() [
Trk::z0];
 
 1773         double errd0_wrtSV     = (*sv_perigee->covariance())( 
Trk::d0, 
Trk::d0 );
 
 1774         double errz0_wrtSV     = (*sv_perigee->covariance())( 
Trk::z0, 
Trk::z0 );
 
 1778         ( m_trkDecors.at(kPt)    )( *trk ) = pt_wrtSV;
 
 1779         ( m_trkDecors.at(
kEta)   )( *trk ) = eta_wrtSV;
 
 1780         ( m_trkDecors.at(
kPhi)   )( *trk ) = phi_wrtSV;
 
 1781         ( m_trkDecors.at(kD0)    )( *trk ) = d0_wrtSV;
 
 1782         ( m_trkDecors.at(kZ0)    )( *trk ) = z0_wrtSV;
 
 1783         ( m_trkDecors.at(kErrP)  )( *trk ) = errP_wrtSV;
 
 1784         ( m_trkDecors.at(kErrD0) )( *trk ) = errd0_wrtSV;
 
 1785         ( m_trkDecors.at(kErrZ0) )( *trk ) = errz0_wrtSV;
 
 1786         ( m_trkDecors.at(kChi2SV))( *trk ) = chi2AtSV;
 
 1788         (*m_decor_is_svtrk_final)( *trk ) = 
true;
 
 1790         TLorentzVector p4wrtSV_pion;
 
 1791         TLorentzVector p4wrtSV_electron;
 
 1792         TLorentzVector p4wrtSV_proton;
 
 1800           if( !is_associatedAcc(*trk) ) {
 
 1801             sumP4_selected += p4wrtSV_pion;
 
 1804           sumP4_selected += p4wrtSV_pion;
 
 1807         sumP4_pion     += p4wrtSV_pion;
 
 1808         sumP4_electron += p4wrtSV_electron;
 
 1809         sumP4_proton   += p4wrtSV_proton;
 
 1811         ATH_MSG_VERBOSE(
" > " << __FUNCTION__ << 
": > Track index " << trk->index() << 
": end." );
 
 1816       ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Final Sec.Vertex=" << wrkvrt.nTracksTotal() <<
", " 
 1817                     <<wrkvrt.vertex.perp() <<
", "<<wrkvrt.vertex.z() <<
", " 
 1818                     <<wrkvrt.vertex.phi() <<
", mass = "<< sumP4_pion.M() << 
"," << sumP4_electron.M() );
 
 1821       float perigee_x_trk1 = 0.0;
 
 1822       float perigee_y_trk1 = 0.0;
 
 1823       float perigee_z_trk1 = 0.0;      
 
 1824       float perigee_x_trk2 = 0.0;
 
 1825       float perigee_y_trk2 = 0.0;
 
 1826       float perigee_z_trk2 = 0.0;      
 
 1827       float perigee_px_trk1 = 0.0;
 
 1828       float perigee_py_trk1 = 0.0;
 
 1829       float perigee_pz_trk1 = 0.0;      
 
 1830       float perigee_px_trk2 = 0.0;
 
 1831       float perigee_py_trk2 = 0.0;
 
 1832       float perigee_pz_trk2 = 0.0;
 
 1833       float perigee_cov_xx_trk1 = 0.0;
 
 1834       float perigee_cov_xy_trk1 = 0.0;
 
 1835       float perigee_cov_xz_trk1 = 0.0;
 
 1836       float perigee_cov_yy_trk1 = 0.0;
 
 1837       float perigee_cov_yz_trk1 = 0.0;
 
 1838       float perigee_cov_zz_trk1 = 0.0;
 
 1839       float perigee_cov_xx_trk2 = 0.0;
 
 1840       float perigee_cov_xy_trk2 = 0.0;
 
 1841       float perigee_cov_xz_trk2 = 0.0;
 
 1842       float perigee_cov_yy_trk2 = 0.0;
 
 1843       float perigee_cov_yz_trk2 = 0.0;
 
 1844       float perigee_cov_zz_trk2 = 0.0;   
 
 1845       float perigee_d0_trk1 = 0.0;
 
 1846       float perigee_d0_trk2 = 0.0;
 
 1847       float perigee_z0_trk1 = 0.0;
 
 1848       float perigee_z0_trk2 = 0.0;
 
 1849       float perigee_qOverP_trk1 = 0.0;
 
 1850       float perigee_qOverP_trk2 = 0.0;
 
 1851       float perigee_theta_trk1 = 0.0;
 
 1852       float perigee_theta_trk2 = 0.0;
 
 1853       float perigee_phi_trk1 = 0.0;
 
 1854       float perigee_phi_trk2 = 0.0;
 
 1855       int perigee_charge_trk1 = 0;
 
 1856       int perigee_charge_trk2 = 0;   
 
 1857       float perigee_distance = 9999.0;
 
 1860       float vPos = (vDist.x() * wrkvrt.vertexMom.Px() + vDist.y() * wrkvrt.vertexMom.Py() + vDist.z() * wrkvrt.vertexMom.Pz()) / wrkvrt.vertexMom.Rho();
 
 1861       float vPosMomAngT = (vDist.x() * wrkvrt.vertexMom.Px() + vDist.y() * wrkvrt.vertexMom.Py()) / vDist.perp() / wrkvrt.vertexMom.Pt();
 
 1862       float vPosMomAng3D = (vDist.x() * wrkvrt.vertexMom.Px() + vDist.y() * wrkvrt.vertexMom.Py() + vDist.z() * wrkvrt.vertexMom.Pz()) / (vDist.norm() * wrkvrt.vertexMom.Rho());      
 
 1863       float dphi_trk1 = 0.0;
 
 1864       float dphi_trk2 = 0.0; 
 
 1866       if (m_jp.doDisappearingTrackVertexing){
 
 1868         const auto* track1 = trackChi2Pairs[0].first;
 
 1870         auto sv_perigee1 = m_trackToVertexTool->perigeeAtVertex(ctx, *track1, wrkvrt.vertex);
 
 1872           perigee_x_trk1 = sv_perigee1->position().x();
 
 1873           perigee_y_trk1 = sv_perigee1->position().y();
 
 1874           perigee_z_trk1 = sv_perigee1->position().z();      
 
 1875           perigee_px_trk1 = sv_perigee1->momentum().x();
 
 1876           perigee_py_trk1 = sv_perigee1->momentum().y();
 
 1877           perigee_pz_trk1 = sv_perigee1->momentum().z();
 
 1878           perigee_cov_xx_trk1 = (*sv_perigee1->covariance())(0, 0);
 
 1879           perigee_cov_xy_trk1 = (*sv_perigee1->covariance())(0, 1);
 
 1880           perigee_cov_xz_trk1 = (*sv_perigee1->covariance())(0, 2);
 
 1881           perigee_cov_yy_trk1 = (*sv_perigee1->covariance())(1, 1);
 
 1882           perigee_cov_yz_trk1 = (*sv_perigee1->covariance())(1, 2);
 
 1883           perigee_cov_zz_trk1 = (*sv_perigee1->covariance())(2, 2);
 
 1884           perigee_d0_trk1 = sv_perigee1->parameters()[
Trk::d0];
 
 1885           perigee_z0_trk1 = sv_perigee1->parameters()[
Trk::z0];
 
 1886           perigee_qOverP_trk1 = sv_perigee1->parameters()[
Trk::qOverP];
 
 1887           perigee_theta_trk1 = sv_perigee1->parameters()[
Trk::theta];
 
 1888           perigee_phi_trk1 = sv_perigee1->parameters()[
Trk::phi];
 
 1889           perigee_charge_trk1 = sv_perigee1->parameters()[
Trk::qOverP] > 0 ? 1 : -1;
 
 1891           ATH_MSG_DEBUG(
"Failed to obtain perigee for track1 at vertex.");
 
 1895         const auto* track2 = trackChi2Pairs[1].first;
 
 1897         auto sv_perigee2 = m_trackToVertexTool->perigeeAtVertex(ctx, *track2, wrkvrt.vertex);
 
 1899           perigee_x_trk2 = sv_perigee2->position().x();
 
 1900           perigee_y_trk2 = sv_perigee2->position().y();
 
 1901           perigee_z_trk2 = sv_perigee2->position().z();      
 
 1902           perigee_px_trk2 = sv_perigee2->momentum().x();
 
 1903           perigee_py_trk2 = sv_perigee2->momentum().y();
 
 1904           perigee_pz_trk2 = sv_perigee2->momentum().z();
 
 1905           perigee_cov_xx_trk2 = (*sv_perigee2->covariance())(0, 0);
 
 1906           perigee_cov_xy_trk2 = (*sv_perigee2->covariance())(0, 1);
 
 1907           perigee_cov_xz_trk2 = (*sv_perigee2->covariance())(0, 2);
 
 1908           perigee_cov_yy_trk2 = (*sv_perigee2->covariance())(1, 1);
 
 1909           perigee_cov_yz_trk2 = (*sv_perigee2->covariance())(1, 2);
 
 1910           perigee_cov_zz_trk2 = (*sv_perigee2->covariance())(2, 2);
 
 1911           perigee_d0_trk2 = sv_perigee2->parameters()[
Trk::d0];
 
 1912           perigee_z0_trk2 = sv_perigee2->parameters()[
Trk::z0];
 
 1913           perigee_qOverP_trk2 = sv_perigee2->parameters()[
Trk::qOverP];
 
 1914           perigee_theta_trk2 = sv_perigee2->parameters()[
Trk::theta];
 
 1915           perigee_phi_trk2 = sv_perigee2->parameters()[
Trk::phi];
 
 1916           perigee_charge_trk2 = sv_perigee2->parameters()[
Trk::qOverP] > 0 ? 1 : -1;
 
 1918           ATH_MSG_DEBUG(
"Failed to obtain perigee for track2 at vertex.");
 
 1921         if(sv_perigee1 && sv_perigee2){
 
 1922           perigee_distance = sqrt(
 
 1923                              (perigee_x_trk1 - perigee_x_trk2) * (perigee_x_trk1 - perigee_x_trk2) +
 
 1924                              (perigee_y_trk1 - perigee_y_trk2) * (perigee_y_trk1 - perigee_y_trk2) +
 
 1925                              (perigee_z_trk1 - perigee_z_trk2) * (perigee_z_trk1 - perigee_z_trk2)
 
 1928         if(perigee_distance > m_jp.twoTrVrtMaxPerigeeDist) 
continue;
 
 1935       std::vector<double> opAngles;
 
 1937       for( 
auto itr1 = tracks.begin(); itr1 != tracks.end(); ++itr1 ) {
 
 1938         for( 
auto itr2 = 
std::next( itr1 ); itr2 != tracks.end(); ++itr2 ) {
 
 1939           const auto& 
p1 = (*itr1)->p4().Vect();
 
 1940           const auto& 
p2 = (*itr2)->p4().Vect();
 
 1942           opAngles.emplace_back( 
cos );
 
 1945       minOpAng = *( std::max_element( opAngles.begin(), opAngles.end() ) );
 
 1946       if( m_jp.FillNtuple ) m_ntupleVars->get< vector<double> >( 
"SecVtx_MinOpAng" ).emplace_back(minOpAng);
 
 1949       if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 5 );
 
 1952         ATH_MSG_DEBUG(
" > " << __FUNCTION__ << 
": Bad impact parameter signif wrt SV was flagged." );
 
 1955       if (m_jp.doRemoveNonLeptonVertices) {
 
 1957         bool oneLepMatchTrack = 
false;
 
 1958         for (
const auto *trk: tracks) {
 
 1959           if ( 
std::find(m_leptonicTracks.begin(), m_leptonicTracks.end(), trk) != m_leptonicTracks.end() ) {
 
 1960             oneLepMatchTrack = 
true;
 
 1966         if (!oneLepMatchTrack) 
continue;        
 
 1972       wrkvrt.isGood = 
true;
 
 1977       secondaryVertexContainer->emplace_back( 
vertex );
 
 1980       vertex->setPosition( wrkvrt.vertex );
 
 1987       vertex->setFitQuality( wrkvrt.Chi2_core, wrkvrt.ndof_core() );
 
 1990       std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
 
 1991       vertex->setCovariance(fCov);
 
 2012       vtx_pxAcc(*
vertex)                   = wrkvrt.vertexMom.Px();
 
 2013       vtx_pyAcc(*
vertex)                   = wrkvrt.vertexMom.Py();
 
 2014       vtx_pzAcc(*
vertex)                   = wrkvrt.vertexMom.Pz();
 
 2016       vtx_massAcc(*
vertex)                 = wrkvrt.vertexMom.M();
 
 2017       vtx_chargeAcc(*
vertex)               = wrkvrt.Charge;
 
 2019       chi2_coreAcc(*
vertex)                = wrkvrt.Chi2_core;
 
 2020       ndof_coreAcc(*
vertex)                = wrkvrt.ndof_core();
 
 2021       chi2_assocAcc(*
vertex)               = wrkvrt.Chi2;
 
 2022       ndof_assocAcc(*
vertex)               = wrkvrt.ndof();
 
 2024       massAcc(*
vertex)                    = sumP4_pion.M();
 
 2025       mass_eAcc(*
vertex)                  = sumP4_electron.M();
 
 2026       mass_selectedTracksAcc(*
vertex)     = sumP4_selected.M();
 
 2027       minOpAngAcc(*
vertex)                = minOpAng;
 
 2028       num_trksAcc(*
vertex)                = wrkvrt.nTracksTotal();
 
 2029       num_selectedTracksAcc(*
vertex)      = wrkvrt.selectedTrackIndices.size();
 
 2030       num_associatedTracksAcc(*
vertex)    = wrkvrt.associatedTrackIndices.size();
 
 2031       dCloseVrtAcc(*
vertex)               = wrkvrt.closestWrkVrtValue;
 
 2034       if (m_jp.doDisappearingTrackVertexing){      
 
 2076         perigee_x_trk1Acc(*
vertex) = perigee_x_trk1;
 
 2077         perigee_y_trk1Acc(*
vertex) = perigee_y_trk1;
 
 2078         perigee_z_trk1Acc(*
vertex) = perigee_z_trk1;      
 
 2079         perigee_x_trk2Acc(*
vertex) = perigee_x_trk2;
 
 2080         perigee_y_trk2Acc(*
vertex) = perigee_y_trk2;
 
 2081         perigee_z_trk2Acc(*
vertex) = perigee_z_trk2;      
 
 2082         perigee_px_trk1Acc(*
vertex) = perigee_px_trk1;
 
 2083         perigee_py_trk1Acc(*
vertex) = perigee_py_trk1;
 
 2084         perigee_pz_trk1Acc(*
vertex) = perigee_pz_trk1;      
 
 2085         perigee_px_trk2Acc(*
vertex) = perigee_px_trk2;
 
 2086         perigee_py_trk2Acc(*
vertex) = perigee_py_trk2;
 
 2087         perigee_pz_trk2Acc(*
vertex) = perigee_pz_trk2;
 
 2088         perigee_cov_xx_trk1Acc(*
vertex) = perigee_cov_xx_trk1;
 
 2089         perigee_cov_xy_trk1Acc(*
vertex) = perigee_cov_xy_trk1;
 
 2090         perigee_cov_xz_trk1Acc(*
vertex) = perigee_cov_xz_trk1;
 
 2091         perigee_cov_yy_trk1Acc(*
vertex) = perigee_cov_yy_trk1;
 
 2092         perigee_cov_yz_trk1Acc(*
vertex) = perigee_cov_yz_trk1;
 
 2093         perigee_cov_zz_trk1Acc(*
vertex) = perigee_cov_zz_trk1;
 
 2094         perigee_cov_xx_trk2Acc(*
vertex) = perigee_cov_xx_trk2;
 
 2095         perigee_cov_xy_trk2Acc(*
vertex) = perigee_cov_xy_trk2;
 
 2096         perigee_cov_xz_trk2Acc(*
vertex) = perigee_cov_xz_trk2;
 
 2097         perigee_cov_yy_trk2Acc(*
vertex) = perigee_cov_yy_trk2;
 
 2098         perigee_cov_yz_trk2Acc(*
vertex) = perigee_cov_yz_trk2;
 
 2099         perigee_cov_zz_trk2Acc(*
vertex) = perigee_cov_zz_trk2;
 
 2100         perigee_d0_trk1Acc(*
vertex) = perigee_d0_trk1;
 
 2101         perigee_d0_trk2Acc(*
vertex) = perigee_d0_trk2;
 
 2102         perigee_z0_trk1Acc(*
vertex) = perigee_z0_trk1;
 
 2103         perigee_z0_trk2Acc(*
vertex) = perigee_z0_trk2;
 
 2104         perigee_qOverP_trk1Acc(*
vertex) = perigee_qOverP_trk1;
 
 2105         perigee_qOverP_trk2Acc(*
vertex) = perigee_qOverP_trk2;
 
 2106         perigee_theta_trk1Acc(*
vertex) = perigee_theta_trk1;
 
 2107         perigee_theta_trk2Acc(*
vertex) = perigee_theta_trk2;
 
 2108         perigee_phi_trk1Acc(*
vertex) = perigee_phi_trk1;
 
 2109         perigee_phi_trk2Acc(*
vertex) = perigee_phi_trk2;
 
 2110         perigee_charge_trk1Acc(*
vertex) = perigee_charge_trk1;
 
 2111         perigee_charge_trk2Acc(*
vertex) = perigee_charge_trk2;        
 
 2113         vPosMomAngTAcc(*
vertex) = vPosMomAngT;
 
 2114         vPosMomAng3DAcc(*
vertex) = vPosMomAng3D;
 
 2115         dphi_trk1Acc(*
vertex) = dphi_trk1;
 
 2116         dphi_trk2Acc(*
vertex) = dphi_trk2;        
 
 2121       for( 
auto trk_id : wrkvrt.selectedTrackIndices ) {
 
 2129         vertex->addTrackAtVertex( link_trk, 1. );
 
 2133       for( 
auto trk_id : wrkvrt.associatedTrackIndices ) {
 
 2141         vertex->addTrackAtVertex( link_trk, 1. );
 
 2146       if( m_jp.doMapToLocal ) {
 
 2154         if( mappedVtx.
valid ) {
 
 2172       if( m_jp.doTruth ) {
 
 2177       wrkvrtLinkMap[&wrkvrt] = 
vertex;
 
 2182     if( m_jp.FillNtuple ) {
 
 2183       ATH_CHECK( fillAANT_SecondaryVertices( secondaryVertexContainer ) );
 
 2188     if( m_jp.doAugmentDVimpactParametersToMuons     ) { 
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Muon>    ( 
"Muons"     ) ); }
 
 2189     if( m_jp.doAugmentDVimpactParametersToElectrons ) { 
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Electron>( 
"Electrons" ) ); }
 
 2191     } 
catch (
const std::out_of_range& 
e) {
 
 2193       ATH_MSG_WARNING( 
" > " << __FUNCTION__ << 
": out of range error is detected: " << 
e.what()  );
 
 2195       return StatusCode::SUCCESS;
 
 2199       ATH_MSG_WARNING( 
" > " << __FUNCTION__ << 
": some other error is detected."  );
 
 2201       return StatusCode::SUCCESS;
 
 2205     return StatusCode::SUCCESS;
 
 2210   StatusCode VrtSecInclusive::monitorVertexingAlgorithmStep( std::vector<WrkVrt>* workVerticesContainer, 
const std::string& 
name, 
bool final ) {
 
 2212     if( m_jp.FillIntermediateVertices ) {
 
 2219       ATH_CHECK( evtStore()->
retrieve( intermediateVertexContainer, 
"VrtSecInclusive_IntermediateVertices_" + 
name + m_jp.augVerString ) );
 
 2221       for( 
auto& wrkvrt : *workVerticesContainer ) {
 
 2224         intermediateVertexContainer->emplace_back( 
vertex );
 
 2227         vertex->setPosition( wrkvrt.vertex );
 
 2233         int ndof = wrkvrt.ndof();
 
 2237         std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
 
 2238         vertex->setCovariance(fCov);
 
 2242         for( 
auto trk_id : wrkvrt.selectedTrackIndices ) {
 
 2250           vertex->addTrackAtVertex( link_trk, 1. );
 
 2254         for( 
auto trk_id : wrkvrt.associatedTrackIndices ) {
 
 2262           vertex->addTrackAtVertex( link_trk, 1. );
 
 2271     if( !m_jp.FillHist ) 
return StatusCode::SUCCESS;
 
 2273     printWrkSet( workVerticesContainer, Form(
"%s (step %u)", 
name.c_str(), m_vertexingAlgorithmStep) );
 
 2275     unsigned count = std::count_if( workVerticesContainer->begin(), workVerticesContainer->end(),
 
 2276                                     []( 
WrkVrt& 
v ) { return ( v.selectedTrackIndices.size() + v.associatedTrackIndices.size() ) >= 2; } );
 
 2278     if( m_vertexingAlgorithmStep == 0 ) {
 
 2280       const auto compSize = m_selectedTracks.size()*(m_selectedTracks.size() - 1)/2 - m_incomp.size();
 
 2281       m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep, compSize );
 
 2285       m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep, 
count );
 
 2289     m_hists[
"vertexYield"]->GetXaxis()->SetBinLabel( m_vertexingAlgorithmStep+1, 
name.c_str() );
 
 2291     for( 
auto& 
vertex : *workVerticesContainer ) {
 
 2292       auto ntrk = 
vertex.selectedTrackIndices.size() + 
vertex.associatedTrackIndices.size();
 
 2293       if( 
vertex.isGood && ntrk >= 2 ) {
 
 2294         dynamic_cast<TH2F*
>( m_hists[
"vertexYieldNtrk"] )->Fill( ntrk, m_vertexingAlgorithmStep );
 
 2298     m_hists[
"vertexYieldNtrk"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1, 
name.c_str() );
 
 2299     m_hists[
"vertexYieldChi2"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1, 
name.c_str() );
 
 2302     if( !
final ) 
return StatusCode::SUCCESS;
 
 2304     for( 
auto& 
vertex : *workVerticesContainer ) {
 
 2305       auto ntrk = 
vertex.selectedTrackIndices.size() + 
vertex.associatedTrackIndices.size();
 
 2306       if( 
vertex.isGood && ntrk >= 2 ) {
 
 2307         m_hists[
"finalVtxNtrk"] ->Fill( ntrk );
 
 2308         m_hists[
"finalVtxR"]    ->Fill( 
vertex.vertex.perp() );
 
 2309         dynamic_cast<TH2F*
>( m_hists[
"finalVtxNtrkR"] )->Fill( ntrk, 
vertex.vertex.perp() );
 
 2313     return StatusCode::SUCCESS;
 
 2318                                               std::vector<double>& impactParameters,
 
 2319                                               std::vector<double>& impactParErrors){
 
 2321     impactParameters.clear();
 
 2322     impactParErrors.clear();
 
 2324     if( m_jp.trkExtrapolator==1 ){
 
 2325       m_fitSvc->VKalGetImpact(trk, 
vertex, 
static_cast<int>( trk->
charge() ), impactParameters, impactParErrors);
 
 2327     else if( m_jp.trkExtrapolator==2 ){
 
 2328       auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(Gaudi::Hive::currentContext(), *trk, 
vertex );
 
 2329       if( !sv_perigee ) 
return false;
 
 2330       impactParameters.push_back(sv_perigee->parameters() [
Trk::d0]);
 
 2331       impactParameters.push_back(sv_perigee->parameters() [
Trk::z0]);
 
 2332       impactParErrors.push_back((*sv_perigee->covariance())( 
Trk::d0, 
Trk::d0 ));
 
 2333       impactParErrors.push_back((*sv_perigee->covariance())( 
Trk::z0, 
Trk::z0 ));
 
 2336       ATH_MSG_WARNING( 
" > " << __FUNCTION__ << 
": Unknown track extrapolator " << m_jp.trkExtrapolator   );