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 const double roughD0Cut { 100. };
68 const double roughZ0Cut { 50. };
71 std::map<const xAOD::TruthVertex*, bool> matchMap;
74 for(
auto itrk = m_selectedTracks->begin(); itrk != m_selectedTracks->end(); ++itrk ) {
75 for(
auto jtrk =
std::next(itrk); jtrk != m_selectedTracks->end(); ++jtrk ) {
79 const int itrk_id = itrk - m_selectedTracks->begin();
80 const int jtrk_id = jtrk - m_selectedTracks->begin();
87 m_incomp.emplace_back( itrk_id, jtrk_id );
89 if( std::abs( (*itrk)->d0() ) < m_jp.twoTrkVtxFormingD0Cut && std::abs( (*jtrk)->d0() ) < m_jp.twoTrkVtxFormingD0Cut )
continue;
92 baseTracks.emplace_back( *itrk );
93 baseTracks.emplace_back( *jtrk );
95 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kStart );
100 std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
101 StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
102 if(
sc.isFailure() ) {
103 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation fails ");
107 if( initVertex.perp() > maxR ) {
110 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kInitVtxPosition );
112 std::vector<double> impactParameters;
113 std::vector<double> impactParErrors;
115 if( !getSVImpactParameters( *itrk, initVertex, impactParameters, impactParErrors) )
continue;
116 const auto roughD0_itrk = impactParameters.at(TrkParameter::k_d0);
117 const auto roughZ0_itrk = impactParameters.at(TrkParameter::k_z0);
118 if( fabs( impactParameters.at(0)) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) {
122 if( !getSVImpactParameters( *jtrk, initVertex, impactParameters, impactParErrors) )
continue;
123 const auto roughD0_jtrk = impactParameters.at(TrkParameter::k_d0);
124 const auto roughZ0_jtrk = impactParameters.at(TrkParameter::k_z0);
125 if( fabs( impactParameters.at(0) ) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) {
128 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kImpactParamCheck );
130 m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
135 sc = m_fitSvc->VKalVrtFit( baseTracks,
141 if(
sc.isFailure() ) {
144 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kVKalVrtFit );
149 const double vPosMomAngT = ( vDist.x()*wrkvrt.
vertexMom.Px()+vDist.y()*wrkvrt.
vertexMom.Py() ) / vDist.perp() / wrkvrt.
vertexMom.Pt();
155 const double dist_fromPV = vDist.norm();
156 if( m_jp.FillHist ) m_hists[
"2trkVtxDistFromPV"]->Fill( dist_fromPV );
158 if( m_jp.FillNtuple ) {
160 m_ntupleVars->get<
unsigned int>(
"All2TrkVrtNum" )++;
161 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtMass" ) .emplace_back(wrkvrt.
vertexMom.M());
162 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtPt" ) .emplace_back(wrkvrt.
vertexMom.Perp());
163 m_ntupleVars->get< std::vector<int> > (
"All2TrkVrtCharge" ) .emplace_back(wrkvrt.
Charge);
164 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtX" ) .emplace_back(wrkvrt.
vertex.x());
165 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtY" ) .emplace_back(wrkvrt.
vertex.y());
166 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtZ" ) .emplace_back(wrkvrt.
vertex.z());
167 m_ntupleVars->get< std::vector<double> >(
"All2TrkVrtChiSq" ) .emplace_back(wrkvrt.
Chi2);
174 if( m_jp.FillIntermediateVertices ) {
178 for(
const auto *trk: baseTracks ) {
184 vertex->addTrackAtVertex( trackElementLink, 1. );
200 isFakeAcc(*
vertex) =
true;
210 if( m_jp.FillNtuple ) m_ntupleVars->get< std::vector<int> >(
"All2TrkSumBLHits" ).emplace_back( trkiBLHit + trkjBLHit );
213 if( m_jp.FillHist ) m_hists[
"2trkChi2Dist"]->Fill( log10( wrkvrt.
Chi2 ) );
215 if( wrkvrt.
fitQuality() > m_jp.SelVrtChi2Cut) {
216 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": failed to pass chi2 threshold." );
219 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kChi2 );
222 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": attempting form vertex from ( " << itrk_id <<
", " << jtrk_id <<
" )." );
223 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": candidate vertex: "
224 <<
" isGood = " << (wrkvrt.
isGood?
"true" :
"false")
229 <<
", (r, z) = (" << wrkvrt.
vertex.perp()
230 <<
", " << wrkvrt.
vertex.z() <<
")" );
232 for(
const auto* truthVertex : m_tracingTruthVertices ) {
233 Amg::Vector3D vTruth( truthVertex->x(), truthVertex->y(), truthVertex->z() );
236 const auto distance = vReco - vTruth;
249 ATH_MSG_DEBUG (
" > " << __FUNCTION__ <<
": truth-matched candidate! : signif^2 = " <<
s2 );
250 matchMap.emplace( truthVertex,
true );
254 if( m_jp.FillHist ) {
255 dynamic_cast<TH2F*
>( m_hists[
"vPosDist"] )->Fill( wrkvrt.
vertex.perp(), vPos );
256 dynamic_cast<TH2F*
>( m_hists[
"vPosMomAngTDist"] )->Fill( wrkvrt.
vertex.perp(), vPosMomAngT );
257 m_hists[
"vPosMomAngT"] ->Fill( vPosMomAngT );
258 m_hists[
"vPosMomAng3D"] ->Fill( vPosMomAng3D );
261 if( m_jp.doTwoTrSoftBtag ){
262 if(dist_fromPV < m_jp.twoTrVrtMinDistFromPV ){
263 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass the 2tr vertex min distance from PV cut." );
267 if( vPosMomAng3D < m_jp.twoTrVrtAngleCut ){
268 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass the vertex angle cut." );
273 if( m_jp.doPVcompatibilityCut ) {
274 if(
cos( dphi1 ) < -0.8 &&
cos( dphi2 ) < -0.8 ) {
275 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass the vPos cut. (both tracks are opposite against the vertex pos)" );
278 if (m_jp.doTightPVcompatibilityCut && (
cos( dphi1 ) < -0.8 ||
cos( dphi2 ) < -0.8)){
279 ATH_MSG_DEBUG(
" > "<< __FUNCTION__ <<
": failed to pass the tightened vPos cut. (at least one track is opposite against the vertex pos)" );
282 if( vPosMomAngT < -0.8 ) {
283 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass the vPos cut. (pos-mom directions are opposite)" );
286 if( vPos < m_jp.pvCompatibilityCut ) {
287 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass the vPos cut." );
291 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kVposCut );
294 if( m_jp.removeFakeVrt && !m_jp.removeFakeVrtLate ) {
295 if( !this->passedFakeReject( wrkvrt.
vertex, (*itrk), (*jtrk) ) ) {
297 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failed to pass fake rejection algorithm." );
301 if( m_jp.FillHist ) m_hists[
"incompMonitor"]->Fill( kPatternMatch );
303 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": passed fake rejection." );
305 if( m_jp.FillNtuple ) {
307 m_ntupleVars->get<
unsigned int >(
"AfFakVrtNum" )++;
308 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtMass" ) .emplace_back(wrkvrt.
vertexMom.M());
309 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtPt" ) .emplace_back(wrkvrt.
vertexMom.Perp());
310 m_ntupleVars->get< std::vector<int> > (
"AfFakVrtCharge" ) .emplace_back(wrkvrt.
Charge);
311 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtX" ) .emplace_back(wrkvrt.
vertex.x());
312 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtY" ) .emplace_back(wrkvrt.
vertex.y());
313 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtZ" ) .emplace_back(wrkvrt.
vertex.z());
314 m_ntupleVars->get< std::vector<double> >(
"AfFakVrtChiSq" ) .emplace_back(wrkvrt.
Chi2);
318 if( m_jp.FillIntermediateVertices &&
vertex ) {
320 isFakeAcc(*
vertex) =
false;
330 workVerticesContainer->emplace_back( wrkvrt );
332 msg += Form(
" (%d, %d), ", itrk_id, jtrk_id );
334 if( m_jp.FillHist ) {
335 m_hists[
"initVertexDispD0"]->Fill( roughD0_itrk, initVertex.perp() );
336 m_hists[
"initVertexDispD0"]->Fill( roughD0_jtrk, initVertex.perp() );
337 m_hists[
"initVertexDispZ0"]->Fill( roughZ0_itrk, initVertex.z() );
338 m_hists[
"initVertexDispZ0"]->Fill( roughZ0_jtrk, initVertex.z() );
345 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": compatible track pairs = " <<
msg );
347 if( m_jp.FillNtuple ) m_ntupleVars->get<
unsigned int>(
"SizeIncomp" ) = m_incomp.size();
349 if( m_jp.FillHist ) {
350 for(
auto& pair: matchMap ) {
351 if( pair.second ) m_hists[
"nMatchedTruths"]->Fill( 1, pair.first->perp() );
355 return StatusCode::SUCCESS;
360 StatusCode VrtSecInclusive::findNtrackVertices( std::vector<WrkVrt> *workVerticesContainer )
364 const auto compSize = m_selectedTracks->size()*(m_selectedTracks->size() - 1)/2 - m_incomp.size();
365 if( m_jp.FillHist ) { m_hists[
"2trkVerticesDist"]->Fill( compSize ); }
367 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": compatible track pair size = " << compSize );
368 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": incompatible track pair size = " << m_incomp.size() );
371 if( not m_jp.doFastMode ) {
373 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": incompatibility graph finder mode" );
376 workVerticesContainer->clear();
383 std::vector<long int> weit;
385 for(
auto& pair : m_incomp ) {
386 weit.emplace_back( pair.first + 1 );
387 weit.emplace_back( pair.second + 1 );
392 std::vector<long int> solution( m_selectedTracks->size() );
395 long int nEdges = m_incomp.size();
398 long int nTracks =
static_cast<long int>( m_selectedTracks->size() );
406 long int solutionSize { 0 };
409 std::vector<const xAOD::TrackParticle*> baseTracks;
410 std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
412 std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
413 auto pgraph = std::make_unique<Trk::PGraph>();
414 int iterationLimit(2000);
419 pgraph->pgraphm_( weit.data(), nEdges, nTracks, solution.data(), &solutionSize, nth);
421 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": Trk::pgraphm_() output: solutionSize = " << solutionSize );
422 if (0 == iterationLimit--){
423 ATH_MSG_WARNING(
"Iteration limit (2000) reached in VrtSecInclusive::findNtrackVertices, solution size = "<<solutionSize);
426 if(solutionSize <= 0)
break;
427 if(solutionSize == 1)
continue;
431 std::string
msg =
"solution = [ ";
432 for(
int i=0;
i< solutionSize;
i++) {
433 msg += Form(
"%ld, ", solution[
i]-1 );
446 for(
long int i = 0;
i<solutionSize;
i++) {
448 baseTracks.emplace_back( m_selectedTracks->at(solution[
i]-1) );
454 StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
455 if(
sc.isFailure())
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation fails ");
457 m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
459 sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
469 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": FoundAppVrt=" << solutionSize <<
", (r, z) = " << wrkvrt.
vertex.perp() <<
", " << wrkvrt.
vertex.z() <<
", chi2/ndof = " << wrkvrt.
fitQuality() );
471 if(
sc.isFailure() ) {
474 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit failed in 2-trk solution ==> give up.");
478 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit failed ==> retry...");
486 if( itrk == jtrk )
continue;
487 if(
tmp.isGood )
continue;
489 tmp.selectedTrackIndices.clear();
490 tmp.selectedTrackIndices.emplace_back( itrk );
491 tmp.selectedTrackIndices.emplace_back( jtrk );
494 baseTracks.emplace_back( m_selectedTracks->at( itrk ) );
495 baseTracks.emplace_back( m_selectedTracks->at( jtrk ) );
500 sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
501 if(
sc.isFailure() )
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation fails ");
503 m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
505 sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
515 if(
sc.isFailure() )
continue;
523 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Did not find any viable vertex in all 2-trk combinations. Give up.");
530 if(
std::find(
tmp.selectedTrackIndices.begin(),
tmp.selectedTrackIndices.end(), itrk ) !=
tmp.selectedTrackIndices.end() )
continue;
534 tmp.selectedTrackIndices.emplace_back( itrk );
536 for(
auto& jtrk :
tmp.selectedTrackIndices ) { baseTracks.emplace_back( m_selectedTracks->at(jtrk) ); }
541 sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
542 if(
sc.isFailure())
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation fails ");
544 m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
546 sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
556 if(
sc.isFailure() ) {
564 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit succeeded; register the vertex to the list.");
568 workVerticesContainer->emplace_back( wrkvrt );
572 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit succeeded; register the vertex to the list.");
576 workVerticesContainer->emplace_back( wrkvrt );
585 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": rapid finder mode" );
589 std::set<long int> tracks;
592 std::vector<struct Cluster>
clusters;
594 for(
auto& wrkvrt : *workVerticesContainer ) {
596 bool foundCluster =
false;
599 if( (wrkvrt.vertex - cluster.position).norm() < 1.0 ) {
600 for(
auto& itrk : wrkvrt.selectedTrackIndices ) {
601 cluster.tracks.insert( itrk );
608 if( !foundCluster ) {
610 c.position = wrkvrt.vertex;
611 for(
auto& itrk : wrkvrt.selectedTrackIndices ) {
612 c.tracks.insert( itrk );
615 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": added a new cluster" );
621 std::vector<const xAOD::TrackParticle*> baseTracks;
622 std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
624 workVerticesContainer->clear();
628 std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
639 for(
const auto&
index: cluster.tracks) {
641 baseTracks.emplace_back( m_selectedTracks->at(
index ) );
647 StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initVertex, *state );
648 if(
sc.isFailure())
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation fails ");
650 m_fitSvc->setApproximateVertex( initVertex.x(), initVertex.y(), initVertex.z(), *state );
652 sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
662 if(
sc.isFailure() ) {
666 workVerticesContainer->emplace_back( wrkvrt );
671 if (m_jp.truncateWrkVertices){
672 if (workVerticesContainer->size() > m_jp.maxWrkVertices){
673 m_vertexingStatus = 3;
674 workVerticesContainer->resize(m_jp.maxWrkVertices);
682 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": Remove vertices fully contained in other vertices .");
683 while( workVerticesContainer->size() > 1 ) {
684 size_t tmpN = workVerticesContainer->size();
687 for(; iv<tmpN-1; iv++) {
689 for(; jv<tmpN; jv++) {
690 const auto nTCom = nTrkCommon( workVerticesContainer, {iv, jv} );
692 if( nTCom == workVerticesContainer->at(iv).selectedTrackIndices.size() ) { workVerticesContainer->erase(workVerticesContainer->begin()+iv);
break; }
693 else if( nTCom == workVerticesContainer->at(jv).selectedTrackIndices.size() ) { workVerticesContainer->erase(workVerticesContainer->begin()+jv);
break; }
698 if(iv==tmpN-1)
break;
702 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": Identify remaining 2-track vertices with very bad Chi2 and mass (b-tagging).");
703 for(
auto& wrkvrt : *workVerticesContainer ) {
705 if( TMath::Prob( wrkvrt.Chi2, wrkvrt.ndof() ) < m_jp.improveChi2ProbThreshold ) wrkvrt.isGood =
false;
706 if( wrkvrt.selectedTrackIndices.size() != 2 )
continue;
707 if( m_jp.FillHist ) m_hists[
"NtrkChi2Dist"]->Fill( log10( wrkvrt.fitQuality() ) );
710 if( m_jp.FillNtuple) m_ntupleVars->get<
unsigned int>(
"NumInitSecVrt" ) = workVerticesContainer->size();
712 return StatusCode::SUCCESS;
717 StatusCode VrtSecInclusive::rearrangeTracks( std::vector<WrkVrt> *workVerticesContainer )
724 std::vector<long int> processedTracks;
726 unsigned mergeCounter { 0 };
727 unsigned brokenCounter { 0 };
728 unsigned removeTrackCounter { 0 };
733 long int maxSharedTrack;
734 long int worstMatchingVertex;
741 std::map<long int, std::vector<long int> > trackToVertexMap;
744 trackClassification( workVerticesContainer, trackToVertexMap );
747 auto worstChi2 = findWorstChi2ofMaximallySharedTrack( workVerticesContainer, trackToVertexMap, maxSharedTrack, worstMatchingVertex );
750 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": no shared tracks are found --> exit the while loop." );
754 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertex [" << worstMatchingVertex <<
"]: maximally shared track index = " << maxSharedTrack
755 <<
", multiplicity = " << trackToVertexMap.at( maxSharedTrack ).size()
756 <<
", worst chi2_trk = " << worstChi2 );
759 if( worstChi2 < m_jp.TrackDetachCut ) {
764 std::vector< std::pair<unsigned, unsigned> > badPairs;
770 unsigned nShared { 0 };
773 auto& vrtList = trackToVertexMap.at( maxSharedTrack );
775 auto nGood = std::count_if( vrtList.begin(), vrtList.end(), [&](
auto&
v ) { return workVerticesContainer->at(v).isGood; } );
778 std::vector< std::tuple< std::pair<unsigned, unsigned>,
double,
unsigned> > significanceTuple;
779 enum { kIndexPair, kSignificance, kNshared };
781 for(
auto ivrt = vrtList.begin(); ivrt != vrtList.end(); ++ivrt ) {
782 for(
auto jvrt =
std::next( ivrt ); jvrt != vrtList.end(); ++jvrt ) {
783 auto pair = std::pair<unsigned, unsigned>( *ivrt, *jvrt );
785 if( !( workVerticesContainer->at(*ivrt).isGood ) )
continue;
786 if( !( workVerticesContainer->at(*jvrt).isGood ) )
continue;
789 if(
std::find( badPairs.begin(), badPairs.end(), pair ) != badPairs.end() )
continue;
791 auto signif = significanceBetweenVertices( workVerticesContainer->at( *ivrt ), workVerticesContainer->at( *jvrt ) );
793 auto& ivrtTrks = workVerticesContainer->at(*ivrt).selectedTrackIndices;
794 auto& jvrtTrks = workVerticesContainer->at(*jvrt).selectedTrackIndices;
796 auto nSharedTracks = std::count_if( ivrtTrks.begin(), ivrtTrks.end(),
798 return std::find( jvrtTrks.begin(), jvrtTrks.end(), index ) != jvrtTrks.end();
801 significanceTuple.emplace_back( pair, signif, nSharedTracks );
805 if( significanceTuple.empty() ) {
806 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": no vertex pairs are found --> exit the while loop." );
810 auto minSignificanceTuple = std::min_element( significanceTuple.begin(), significanceTuple.end(), [&](
auto&
t1,
auto&
t2 ) { return std::get<kSignificance>(t1) < std::get<kSignificance>(t2); } );
812 indexPair = std::get<kIndexPair> ( *minSignificanceTuple );
813 minSignificance = std::get<kSignificance> ( *minSignificanceTuple );
814 nShared = std::get<kNshared> ( *minSignificanceTuple );
817 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": minSignificance = " << minSignificance );
819 if( minSignificance < m_jp.VertexMergeCut || nShared >= 2 ) {
821 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": attempt to merge vertices " << indexPair.first <<
" and " << indexPair.second );
823 WrkVrt vertex_backup1 = workVerticesContainer->at( indexPair.first );
824 WrkVrt vertex_backup2 = workVerticesContainer->at( indexPair.second );
826 StatusCode sc = mergeVertices( workVerticesContainer->at( indexPair.first ), workVerticesContainer->at( indexPair.second ) );
828 if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill( RECONSTRUCT_NTRK ); }
830 if(
sc.isFailure() ) {
832 workVerticesContainer->at( indexPair.first ) = vertex_backup1;
833 workVerticesContainer->at( indexPair.second ) = vertex_backup2;
834 badPairs.emplace_back( indexPair );
839 workVerticesContainer->at( indexPair.second ).isGood =
false;
846 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Merged vertices " << indexPair.first <<
" and " << indexPair.second <<
". merged vertex multiplicity = " << workVerticesContainer->at( indexPair.first ).selectedTrackIndices.size() );
854 auto& wrkvrt = workVerticesContainer->at( worstMatchingVertex );
856 auto end =
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(), [&](
auto&
index ) { return index == maxSharedTrack; } );
857 wrkvrt.selectedTrackIndices.erase(
end, wrkvrt.selectedTrackIndices.end() );
859 removeTrackCounter++;
861 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": removed track " << maxSharedTrack <<
" from vertex " << worstMatchingVertex );
863 if( wrkvrt.selectedTrackIndices.size() < 2 ) {
864 wrkvrt.isGood =
false;
870 if(
sc.isFailure() ) {
871 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
884 auto& wrkvrt = workVerticesContainer->at( worstMatchingVertex );
886 auto end =
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(), [&](
auto&
index ) { return index == maxSharedTrack; } );
887 wrkvrt.selectedTrackIndices.erase(
end, wrkvrt.selectedTrackIndices.end() );
889 if( wrkvrt.nTracksTotal() >=2 ) {
891 auto wrkvrt_backup = wrkvrt;
893 if(
sc.isFailure() ) {
894 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
895 wrkvrt = wrkvrt_backup;
899 wrkvrt.isGood =
false;
903 removeTrackCounter++;
905 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": removed track " << maxSharedTrack <<
" from vertex " << worstMatchingVertex );
913 for(
auto& wrkvrt : *workVerticesContainer ) {
915 if(!wrkvrt.isGood )
continue;
916 if( wrkvrt.selectedTrackIndices.size() < 3 )
continue;
919 improveVertexChi2( wrkvrt );
920 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
922 if( wrkvrt.nTracksTotal() < 2 ) wrkvrt.
isGood =
false;
926 if( m_jp.FillNtuple ) {
927 m_ntupleVars->get<
unsigned int>(
"NumRearrSecVrt" )=workVerticesContainer->size();
928 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Size of Solution Set: "<< m_ntupleVars->get<
unsigned int>(
"NumRearrSecVrt" ));
931 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
932 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Number of merges = " << mergeCounter <<
", Number of track removal = " << removeTrackCounter <<
", broken vertices = " << brokenCounter );
933 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
935 return StatusCode::SUCCESS;
940 StatusCode VrtSecInclusive::reassembleVertices( std::vector<WrkVrt>* workVerticesContainer )
949 unsigned reassembleCounter { 0 };
952 std::sort( workVerticesContainer->begin(), workVerticesContainer->end(), [](
WrkVrt& v1,
WrkVrt&
v2) { return v1.selectedTrackIndices.size() < v2.selectedTrackIndices.size(); } );
954 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": #vertices = " << workVerticesContainer->size() );
956 for(
auto& wrkvrt : *workVerticesContainer ) {
957 if( !wrkvrt.isGood )
continue;
958 if( wrkvrt.selectedTrackIndices.size() <= 1 )
continue;
960 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertex " << &wrkvrt <<
" #tracks = " << wrkvrt.selectedTrackIndices.size() );
961 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": candidate vertex: "
962 <<
" isGood = " << (wrkvrt.isGood?
"true" :
"false")
963 <<
", #ntrks = " << wrkvrt.nTracksTotal()
964 <<
", #selectedTracks = " << wrkvrt.selectedTrackIndices.size()
965 <<
", #associatedTracks = " << wrkvrt.associatedTrackIndices.size()
966 <<
", chi2/ndof = " << wrkvrt.fitQuality()
967 <<
", (r, z) = (" << wrkvrt.vertex.perp()
968 <<
", " << wrkvrt.vertex.z() <<
")" );
970 std::map<unsigned, std::vector<WrkVrt>::reverse_iterator> mergiableVertex;
971 std::set<std::vector<WrkVrt>::reverse_iterator> mergiableVerticesSet;
973 for(
auto&
index : wrkvrt.selectedTrackIndices ) {
977 mergiableVertex[
index] = workVerticesContainer->rend();
979 std::vector<double> distances;
982 for(
auto ritr = workVerticesContainer->rbegin(); ritr != workVerticesContainer->rend(); ++ritr ) {
983 auto& targetVertex = *ritr;
985 if( &wrkvrt == &targetVertex )
continue;
986 if( wrkvrt.selectedTrackIndices.size() >= targetVertex.selectedTrackIndices.size() )
continue;
989 std::vector<double> impactParameters;
990 std::vector<double> impactParErrors;
992 if( !getSVImpactParameters(trk,targetVertex.vertex,impactParameters,impactParErrors) )
continue;
994 const auto&
distance = hypot( impactParameters.at(0), impactParameters.at(1) );
997 if( std::abs( impactParameters.at(0) ) > m_jp.reassembleMaxImpactParameterD0 )
continue;
998 if( std::abs( impactParameters.at(1) ) > m_jp.reassembleMaxImpactParameterZ0 )
continue;
1000 mergiableVertex[
index] = ritr;
1001 mergiableVerticesSet.emplace( ritr );
1005 auto min_distance = !distances.empty() ? *(std::min_element( distances.begin(), distances.end() )) :
AlgConsts::invalidFloat;
1007 if( mergiableVertex[
index] == workVerticesContainer->rend() ) {
1008 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": track " << trk <<
" --> none : min distance = " << min_distance );
1010 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": track " << trk <<
" --> " << &( *(mergiableVertex[
index]) ) <<
" --> size = " << mergiableVertex[
index]->selectedTrackIndices.size() <<
": min distance = " << min_distance );
1015 size_t count_mergiable = std::count_if( mergiableVertex.begin(), mergiableVertex.end(),
1016 [&](
const std::pair<
unsigned, std::vector<WrkVrt>::reverse_iterator>&
p ) {
1017 return p.second != workVerticesContainer->rend(); } );
1019 if( mergiableVerticesSet.size() == 1 && count_mergiable == wrkvrt.selectedTrackIndices.size() ) {
1021 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": identified a unique association destination vertex" );
1023 WrkVrt& destination = *( mergiableVertex.begin()->second );
1027 if(
sc.isFailure() ) {
1028 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": failure in vertex merging" );
1031 improveVertexChi2( destination );
1033 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": merged destination vertex: "
1034 <<
" isGood = " << (destination.
isGood?
"true" :
"false")
1038 <<
", chi2/ndof = " << destination.
fitQuality()
1039 <<
", (r, z) = (" << destination.
vertex.perp()
1040 <<
", " << destination.
vertex.z() <<
")" );
1042 if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill( REASSEMBLE ); }
1046 reassembleCounter++;
1052 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1053 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": reassembled vertices = " << reassembleCounter );
1054 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1056 return StatusCode::SUCCESS;
1061 StatusCode VrtSecInclusive::associateNonSelectedTracks( std::vector<WrkVrt>* workVerticesContainer )
1070 if( !m_decor_isAssociated ) m_decor_isAssociated = std::make_unique< SG::AuxElement::Decorator<char> >(
"is_associated" + m_jp.augVerString );
1072 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": #verticess = " << workVerticesContainer->size() );
1074 unsigned associateCounter { 0 };
1077 for(
auto& wrkvrt : *workVerticesContainer ) {
1079 if( !wrkvrt.isGood )
continue;
1080 if( wrkvrt.selectedTrackIndices.size() <= 1 )
continue;
1082 improveVertexChi2( wrkvrt );
1084 wrkvrt.Chi2_core = wrkvrt.Chi2;
1086 auto& vertexPos = wrkvrt.vertex;
1088 std::vector<double> distanceToPVs;
1090 for(
const auto*
pv : *pvs ) {
1093 const auto& minDistance = *( std::min_element( distanceToPVs.begin(), distanceToPVs.end() ) );
1095 if( minDistance < m_jp.associateMinDistanceToPV )
continue;
1098 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertex pos = (" << vertexPos.x() <<
", " << vertexPos.y() <<
", " << vertexPos.z() <<
"), "
1099 "#selected = " << wrkvrt.selectedTrackIndices.size() <<
", #assoc = " << wrkvrt.associatedTrackIndices.size() );
1101 std::vector<const xAOD::TrackParticle*>
candidates;
1104 for(
auto itr = allTracks->
begin(); itr != allTracks->
end(); ++itr ) {
1105 const auto* trk = *itr;
1109 auto result = std::find_if( workVerticesContainer->begin(), workVerticesContainer->end(),
1111 auto found = std::find_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
1112 [&]( long int index ) {
1114 if (m_jp.doSelectTracksFromElectrons || m_jp.doSelectIDAndGSFTracks) {
1115 const xAOD::TrackParticle *id_tr;
1116 id_tr = xAOD::EgammaHelpers::getOriginalTrackParticleFromGSF(m_selectedTracks->at(index));
1117 return trk == m_selectedTracks->at(index) or trk == id_tr;
1120 return trk == m_selectedTracks->at(index);
1125 if(
result != workVerticesContainer->end() )
continue;
1130 auto result = std::find_if( m_associatedTracks->begin(), m_associatedTracks->end(),
1131 [&] (
const auto* atrk) { return trk == atrk; } );
1132 if(
result != m_associatedTracks->end() )
continue;
1139 if( trk->pt() < m_jp.associatePtCut )
continue;
1142 if( trk->chiSquared() / trk->numberDoF() > m_jp.associateChi2Cut )
continue;
1145 if( !checkTrackHitPatternToVertexOuterOnly( trk, vertexPos ) )
continue;
1148 std::vector<double> impactParameters;
1149 std::vector<double> impactParErrors;
1151 if( !getSVImpactParameters( trk, vertexPos, impactParameters, impactParErrors) )
continue;
1153 if( std::abs( impactParameters.at(0) ) / sqrt( impactParErrors.at(0) ) > m_jp.associateMaxD0Signif )
continue;
1154 if( std::abs( impactParameters.at(1) ) / sqrt( impactParErrors.at(1) ) > m_jp.associateMaxZ0Signif )
continue;
1157 <<
": d0 to vtx = " << impactParameters.at(k_d0)
1158 <<
", z0 to vtx = " << impactParameters.at(k_z0)
1159 <<
", distance to vtx = " << hypot( impactParameters.at(k_d0), impactParameters.at(k_z0) ) );
1167 std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
1171 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": attempting to associate track = " << trk );
1174 WrkVrt wrkvrt_backup = wrkvrt;
1176 m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
1178 std::vector<const xAOD::TrackParticle*> baseTracks;
1179 std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
1183 for(
const auto&
index : wrkvrt.selectedTrackIndices ) {
1184 baseTracks.emplace_back( m_selectedTracks->at(
index ) );
1187 for(
const auto&
index : wrkvrt.associatedTrackIndices ) {
1188 baseTracks.emplace_back( m_associatedTracks->at(
index ) );
1192 baseTracks.emplace_back( trk );
1198 StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initPos, *state );
1200 if(
sc.isFailure() )
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation failed.");
1202 const auto& diffPos = initPos - vertexPos;
1204 if( diffPos.norm() > 10. ) {
1206 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": approx vertex as original" );
1207 m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
1211 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": approx vertex set to (" << initPos.x() <<
", " << initPos.y() <<
", " << initPos.z() <<
")" );
1212 m_fitSvc->setApproximateVertex( initPos.x(), initPos.y(), initPos.z(), *state );
1218 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": now vertex fitting..." );
1220 StatusCode sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
1230 if(
sc.isFailure() ) {
1231 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit failure. Revert to backup");
1232 wrkvrt = wrkvrt_backup;
1234 if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 1 );
1240 if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 0 );
1242 auto&
cov = wrkvrt.vertexCov;
1244 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": succeeded in associating. New vertex pos = (" << vertexPos.perp() <<
", " << vertexPos.z() <<
", " << vertexPos.perp()*vertexPos.phi() <<
")" );
1245 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) <<
")" );
1249 wrkvrt.associatedTrackIndices.emplace_back( m_associatedTracks->size() );
1251 m_associatedTracks->emplace_back( trk );
1252 (*m_decor_isAssociated)( *trk ) =
true;
1258 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1259 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": total associated number of tracks = " << associateCounter );
1260 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1262 return StatusCode::SUCCESS;
1267 StatusCode VrtSecInclusive::mergeByShuffling( std::vector<WrkVrt> *workVerticesContainer )
1270 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": #verticess = " << workVerticesContainer->size() );
1272 unsigned mergeCounter { 0 };
1275 std::sort( workVerticesContainer->begin(), workVerticesContainer->end(), [](
WrkVrt& v1,
WrkVrt&
v2) { return v1.selectedTrackIndices.size() < v2.selectedTrackIndices.size(); } );
1278 for(
auto& wrkvrt : *workVerticesContainer ) {
1279 if( !wrkvrt.isGood )
continue;
1280 if( wrkvrt.selectedTrackIndices.size() <= 1 )
continue;
1283 for(
auto ritr = workVerticesContainer->rbegin(); ritr != workVerticesContainer->rend(); ++ritr ) {
1284 auto& vertexToMerge = *ritr;
1286 if( !vertexToMerge.isGood )
continue;
1287 if( vertexToMerge.selectedTrackIndices.size() <= 1 )
continue;
1288 if( &wrkvrt == &vertexToMerge )
continue;
1289 if( vertexToMerge.selectedTrackIndices.size() < wrkvrt.selectedTrackIndices.size() )
continue;
1291 const double& significance = significanceBetweenVertices( wrkvrt, vertexToMerge );
1293 if( significance > m_jp.mergeByShufflingMaxSignificance )
continue;
1295 bool mergeFlag {
false };
1298 <<
": vertex " << &wrkvrt <<
" #tracks = " << wrkvrt.selectedTrackIndices.size()
1299 <<
" --> to Merge : " << &vertexToMerge <<
", #tracks = " << vertexToMerge.selectedTrackIndices.size()
1300 <<
" significance = " << significance );
1305 if( m_jp.doSuggestedRefitOnMerging && !mergeFlag ) {
1306 WrkVrt testVertex = wrkvrt;
1308 if(
sc.isFailure() ) {
1312 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1313 if( signif < min_signif ) min_signif = signif;
1315 if( signif < m_jp.mergeByShufflingAllowance ) {
1316 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method1: vertexToMerge " << &vertexToMerge <<
": test signif = " << signif );
1321 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif1"]->Fill( log10( min_signif ) );
1322 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE1 ); }
1327 if( m_jp.doMagnetMerging && !mergeFlag ) {
1330 for(
auto&
index : vertexToMerge.selectedTrackIndices ) {
1332 WrkVrt testVertex = wrkvrt;
1336 if(
sc.isFailure() ) {
1340 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1341 if( signif < min_signif ) min_signif = signif;
1343 if( signif < m_jp.mergeByShufflingAllowance ) {
1344 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method2: vertexToMerge " << &vertexToMerge <<
" track index " <<
index <<
": test signif = " << signif );
1351 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif2"]->Fill( log10( min_signif ) );
1353 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE2 ); }
1357 if( m_jp.doWildMerging && !mergeFlag ) {
1359 WrkVrt testVertex = wrkvrt;
1361 for(
auto&
index : vertexToMerge.selectedTrackIndices ) {
1366 if(
sc.isFailure() ) {
1370 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1371 if( signif < min_signif ) min_signif = signif;
1373 if( signif < m_jp.mergeByShufflingAllowance ) {
1374 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method3: vertexToMerge " << &vertexToMerge <<
": test signif = " << signif );
1378 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif3"]->Fill( log10( min_signif ) );
1379 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE3 ); }
1386 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertexToMerge " << &vertexToMerge <<
" ==> min signif = " << min_signif <<
" judged to merge" );
1388 auto vertexToMerge_backup = vertexToMerge;
1389 auto wrkvrt_backup = wrkvrt;
1391 StatusCode sc = mergeVertices( vertexToMerge, wrkvrt );
1392 if(
sc.isFailure() ) {
1393 vertexToMerge = vertexToMerge_backup;
1394 wrkvrt = wrkvrt_backup;
1398 improveVertexChi2( wrkvrt );
1407 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1408 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Number of merges = " << mergeCounter );
1409 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1411 return StatusCode::SUCCESS;
1416 StatusCode VrtSecInclusive::mergeFinalVertices( std::vector<WrkVrt> *workVerticesContainer )
1419 unsigned mergeCounter { 0 };
1425 for(
auto& wrkvrt : *workVerticesContainer) {
1431 auto minDistance = findMinVerticesPair( workVerticesContainer, indexPair, &VrtSecInclusive::distanceBetweenVertices );
1437 auto& v1 = workVerticesContainer->at(indexPair.first);
1438 auto&
v2 = workVerticesContainer->at(indexPair.second);
1440 const double averageRadius = ( v1.vertex.perp() +
v2.vertex.perp() ) / 2.0;
1442 if( minDistance > m_jp.VertexMergeFinalDistCut + m_jp.VertexMergeFinalDistScaling * averageRadius ) {
1443 ATH_MSG_DEBUG(
"Vertices " << indexPair.first <<
" and " << indexPair.second
1444 <<
" are separated by distance " << minDistance );
1448 ATH_MSG_DEBUG(
"Merging FINAL vertices " << indexPair.first <<
" and " << indexPair.second
1449 <<
" which are separated by distance "<< minDistance );
1452 if(
sc.isFailure() ) {}
1453 if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill(
FINAL ); }
1455 improveVertexChi2( v1 );
1461 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1462 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Number of merges = " << mergeCounter );
1463 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1465 return StatusCode::SUCCESS;
1472 StatusCode VrtSecInclusive::refitAndSelectGoodQualityVertices( std::vector<WrkVrt> *workVerticesContainer )
1482 ATH_CHECK( evtStore()->
retrieve( secondaryVertexContainer,
"VrtSecInclusive_" + m_jp.secondaryVerticesContainerName + m_jp.augVerString ) );
1487 enum { kPt, kEta, kPhi, kD0, kZ0, kErrP, kErrD0, kErrZ0, kChi2SV };
1488 if( m_trkDecors.empty() ) {
1499 if( !m_decor_is_svtrk_final ) m_decor_is_svtrk_final = std::make_unique< SG::AuxElement::Decorator<char> >(
"is_svtrk_final" + m_jp.augVerString );
1501 std::map<const WrkVrt*, const xAOD::Vertex*> wrkvrtLinkMap;
1504 const auto& ctx = Gaudi::Hive::currentContext();
1506 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": input #vertices = " << workVerticesContainer->size() );
1509 for(
auto& wrkvrt : *workVerticesContainer ) {
1511 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": candidate vertex: "
1512 <<
" isGood = " << (wrkvrt.isGood?
"true" :
"false")
1513 <<
", #ntrks = " << wrkvrt.nTracksTotal()
1514 <<
", #selectedTracks = " << wrkvrt.selectedTrackIndices.size()
1515 <<
", #associatedTracks = " << wrkvrt.associatedTrackIndices.size()
1517 <<
", (r, z) = (" << wrkvrt.vertex.perp()
1518 <<
", " << wrkvrt.vertex.z() <<
")" );
1520 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 0 );
1522 if( m_jp.removeFakeVrt && m_jp.removeFakeVrtLate ) {
1523 removeInconsistentTracks( wrkvrt );
1526 if( wrkvrt.nTracksTotal() < 2 ) {
1527 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": ntrk < 2 --> rejected." );
1531 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 1 );
1535 if( wrkvrt.vertex.perp() < 31.0 ) {
1538 wrkvrt.selectedTrackIndices.erase(
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
1539 [&](
auto&
index ) {
1540 auto* trk = m_selectedTracks->at( index );
1544 wrkvrt.selectedTrackIndices.end() );
1547 wrkvrt.associatedTrackIndices.erase(
std::remove_if( wrkvrt.associatedTrackIndices.begin(), wrkvrt.associatedTrackIndices.end(),
1548 [&](
auto&
index ) {
1549 auto* trk = m_associatedTracks->at( index );
1553 wrkvrt.associatedTrackIndices.end() );
1561 if( m_jp.doFinalImproveChi2 ) {
1565 improveVertexChi2( wrkvrt );
1567 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1572 if( wrkvrt.nTracksTotal() < 2 )
continue;
1575 if( wrkvrt.selectedTrackIndices.size() < 2 )
continue;
1578 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 2 );
1585 if(
sc.isFailure() ) {
1587 auto indices = wrkvrt.associatedTrackIndices;
1589 wrkvrt.associatedTrackIndices.clear();
1590 sc = refitVertex( wrkvrt );
1591 if(
sc.isFailure() ) {
1592 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
1595 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1600 sc = refitVertex( wrkvrt );
1601 if(
sc.isFailure() || TMath::Prob( wrkvrt.Chi2, wrkvrt.ndof() ) < m_jp.improveChi2ProbThreshold ) {
1602 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
1609 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1613 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 3 );
1618 if( m_jp.FillNtuple ) m_ntupleVars->get<
unsigned int>(
"NumSecVrt" )++;
1620 TLorentzVector sumP4_pion;
1621 TLorentzVector sumP4_electron;
1622 TLorentzVector sumP4_proton;
1625 bool good_flag =
true;
1627 std::map<const std::deque<long int>*,
const std::vector<const xAOD::TrackParticle*>&> indicesSet
1629 { &(wrkvrt.selectedTrackIndices), *m_selectedTracks },
1630 { &(wrkvrt.associatedTrackIndices), *m_associatedTracks }
1633 for(
auto& pair : indicesSet ) {
1635 const auto*
indices = pair.first;
1636 const auto& tracks = pair.second;
1638 for(
const auto& itrk : *
indices ) {
1639 const auto* trk = tracks.at( itrk );
1640 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
1642 ATH_MSG_INFO(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Failed in obtaining the SV perigee!" );
1650 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": sv perigee could not be obtained --> rejected" );
1654 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 4 );
1657 std::vector<const xAOD::TrackParticle*> tracks;
1658 std::vector< std::pair<const xAOD::TrackParticle*, double> > trackChi2Pairs;
1662 for(
auto& pair : indicesSet ) {
1663 for(
const auto&
index : *pair.first ) tracks.emplace_back( pair.second.at(
index ) );
1666 auto trkitr = tracks.begin();
1667 auto chi2itr = wrkvrt.Chi2PerTrk.begin();
1669 for( ; ( trkitr!=tracks.end() && chi2itr!=wrkvrt.Chi2PerTrk.end() ); ++trkitr, ++chi2itr ) {
1670 trackChi2Pairs.emplace_back( *trkitr, *chi2itr );
1676 TLorentzVector sumP4_selected;
1678 bool badIPflag {
false };
1681 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Track loop: size = " << tracks.size() );
1682 for(
auto& pair : trackChi2Pairs ) {
1684 const auto* trk = pair.first;
1685 const auto& chi2AtSV = pair.second;
1687 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": start." );
1690 fillTrackSummary( trk_summary, trk );
1696 double trk_pt = trk->pt();
1697 double trk_eta = trk->eta();
1698 double trk_phi = trk->phi();
1700 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": in vrt chg/pt/phi/eta = "
1701 << trk->charge() <<
","
1708 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Get the prigee of the track at the vertex." );
1710 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
1712 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Failed in obtaining the SV perigee!" );
1714 for(
auto& pair : m_trkDecors ) {
1717 (*m_decor_is_svtrk_final)( *trk ) =
true;
1721 double qOverP_wrtSV = sv_perigee->parameters() [
Trk::qOverP];
1722 double theta_wrtSV = sv_perigee->parameters() [
Trk::theta];
1723 double p_wrtSV = 1.0 / std::abs( qOverP_wrtSV );
1724 double pt_wrtSV = p_wrtSV *
sin( theta_wrtSV );
1725 double eta_wrtSV = -
log(
tan( theta_wrtSV/2. ) );
1726 double phi_wrtSV = sv_perigee->parameters() [
Trk::phi];
1727 double d0_wrtSV = sv_perigee->parameters() [
Trk::d0];
1728 double z0_wrtSV = sv_perigee->parameters() [
Trk::z0];
1729 double errd0_wrtSV = (*sv_perigee->covariance())(
Trk::d0,
Trk::d0 );
1730 double errz0_wrtSV = (*sv_perigee->covariance())(
Trk::z0,
Trk::z0 );
1734 ( m_trkDecors.at(kPt) )( *trk ) = pt_wrtSV;
1735 ( m_trkDecors.at(kEta) )( *trk ) = eta_wrtSV;
1736 ( m_trkDecors.at(kPhi) )( *trk ) = phi_wrtSV;
1737 ( m_trkDecors.at(kD0) )( *trk ) = d0_wrtSV;
1738 ( m_trkDecors.at(kZ0) )( *trk ) = z0_wrtSV;
1739 ( m_trkDecors.at(kErrP) )( *trk ) = errP_wrtSV;
1740 ( m_trkDecors.at(kErrD0) )( *trk ) = errd0_wrtSV;
1741 ( m_trkDecors.at(kErrZ0) )( *trk ) = errz0_wrtSV;
1742 ( m_trkDecors.at(kChi2SV))( *trk ) = chi2AtSV;
1744 (*m_decor_is_svtrk_final)( *trk ) =
true;
1746 TLorentzVector p4wrtSV_pion;
1747 TLorentzVector p4wrtSV_electron;
1748 TLorentzVector p4wrtSV_proton;
1756 if( !is_associatedAcc(*trk) ) {
1757 sumP4_selected += p4wrtSV_pion;
1760 sumP4_selected += p4wrtSV_pion;
1763 sumP4_pion += p4wrtSV_pion;
1764 sumP4_electron += p4wrtSV_electron;
1765 sumP4_proton += p4wrtSV_proton;
1767 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": end." );
1772 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Final Sec.Vertex=" << wrkvrt.nTracksTotal() <<
", "
1773 <<wrkvrt.vertex.perp() <<
", "<<wrkvrt.vertex.z() <<
", "
1774 <<wrkvrt.vertex.phi() <<
", mass = "<< sumP4_pion.M() <<
"," << sumP4_electron.M() );
1781 std::vector<double> opAngles;
1783 for(
auto itr1 = tracks.begin(); itr1 != tracks.end(); ++itr1 ) {
1784 for(
auto itr2 =
std::next( itr1 ); itr2 != tracks.end(); ++itr2 ) {
1785 const auto&
p1 = (*itr1)->p4().Vect();
1786 const auto&
p2 = (*itr2)->p4().Vect();
1788 opAngles.emplace_back(
cos );
1791 minOpAng = *( std::max_element( opAngles.begin(), opAngles.end() ) );
1792 if( m_jp.FillNtuple ) m_ntupleVars->get< vector<double> >(
"SecVtx_MinOpAng" ).emplace_back(minOpAng);
1795 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 5 );
1798 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Bad impact parameter signif wrt SV was flagged." );
1801 if (m_jp.doRemoveNonLeptonVertices) {
1803 bool oneLepMatchTrack =
false;
1804 for (
const auto *trk: tracks) {
1805 if (
std::find(m_leptonicTracks->begin(), m_leptonicTracks->end(), trk) != m_leptonicTracks->end() ) {
1806 oneLepMatchTrack =
true;
1812 if (!oneLepMatchTrack)
continue;
1818 wrkvrt.isGood =
true;
1823 secondaryVertexContainer->emplace_back(
vertex );
1826 vertex->setPosition( wrkvrt.vertex );
1833 vertex->setFitQuality( wrkvrt.Chi2_core, wrkvrt.ndof_core() );
1836 std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
1837 vertex->setCovariance(fCov);
1858 vtx_pxAcc(*
vertex) = wrkvrt.vertexMom.Px();
1859 vtx_pyAcc(*
vertex) = wrkvrt.vertexMom.Py();
1860 vtx_pzAcc(*
vertex) = wrkvrt.vertexMom.Pz();
1862 vtx_massAcc(*
vertex) = wrkvrt.vertexMom.M();
1863 vtx_chargeAcc(*
vertex) = wrkvrt.Charge;
1865 chi2_coreAcc(*
vertex) = wrkvrt.Chi2_core;
1866 ndof_coreAcc(*
vertex) = wrkvrt.ndof_core();
1867 chi2_assocAcc(*
vertex) = wrkvrt.Chi2;
1868 ndof_assocAcc(*
vertex) = wrkvrt.ndof();
1870 massAcc(*
vertex) = sumP4_pion.M();
1871 mass_eAcc(*
vertex) = sumP4_electron.M();
1872 mass_selectedTracksAcc(*
vertex) = sumP4_selected.M();
1873 minOpAngAcc(*
vertex) = minOpAng;
1874 num_trksAcc(*
vertex) = wrkvrt.nTracksTotal();
1875 num_selectedTracksAcc(*
vertex) = wrkvrt.selectedTrackIndices.size();
1876 num_associatedTracksAcc(*
vertex) = wrkvrt.associatedTrackIndices.size();
1877 dCloseVrtAcc(*
vertex) = wrkvrt.closestWrkVrtValue;
1881 for(
auto trk_id : wrkvrt.selectedTrackIndices ) {
1889 vertex->addTrackAtVertex( link_trk, 1. );
1893 for(
auto trk_id : wrkvrt.associatedTrackIndices ) {
1901 vertex->addTrackAtVertex( link_trk, 1. );
1906 if( m_jp.doMapToLocal ) {
1914 if( mappedVtx.
valid ) {
1932 if( m_jp.doTruth ) {
1937 wrkvrtLinkMap[&wrkvrt] =
vertex;
1942 if( m_jp.FillNtuple ) {
1943 ATH_CHECK( fillAANT_SecondaryVertices( secondaryVertexContainer ) );
1948 if( m_jp.doAugmentDVimpactParametersToMuons ) {
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Muon> (
"Muons" ) ); }
1949 if( m_jp.doAugmentDVimpactParametersToElectrons ) {
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Electron>(
"Electrons" ) ); }
1951 }
catch (
const std::out_of_range&
e) {
1953 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": out of range error is detected: " <<
e.what() );
1955 return StatusCode::SUCCESS;
1959 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": some other error is detected." );
1961 return StatusCode::SUCCESS;
1965 return StatusCode::SUCCESS;
1970 StatusCode VrtSecInclusive::monitorVertexingAlgorithmStep( std::vector<WrkVrt>* workVerticesContainer,
const std::string&
name,
bool final ) {
1972 if( m_jp.FillIntermediateVertices ) {
1979 ATH_CHECK( evtStore()->
retrieve( intermediateVertexContainer,
"VrtSecInclusive_IntermediateVertices_" +
name + m_jp.augVerString ) );
1981 for(
auto& wrkvrt : *workVerticesContainer ) {
1984 intermediateVertexContainer->emplace_back(
vertex );
1987 vertex->setPosition( wrkvrt.vertex );
1993 int ndof = wrkvrt.ndof();
1997 std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
1998 vertex->setCovariance(fCov);
2002 for(
auto trk_id : wrkvrt.selectedTrackIndices ) {
2010 vertex->addTrackAtVertex( link_trk, 1. );
2014 for(
auto trk_id : wrkvrt.associatedTrackIndices ) {
2022 vertex->addTrackAtVertex( link_trk, 1. );
2031 if( !m_jp.FillHist )
return StatusCode::SUCCESS;
2033 printWrkSet( workVerticesContainer, Form(
"%s (step %u)",
name.c_str(), m_vertexingAlgorithmStep) );
2035 unsigned count = std::count_if( workVerticesContainer->begin(), workVerticesContainer->end(),
2036 [](
WrkVrt&
v ) { return ( v.selectedTrackIndices.size() + v.associatedTrackIndices.size() ) >= 2; } );
2038 if( m_vertexingAlgorithmStep == 0 ) {
2040 const auto compSize = m_selectedTracks->size()*(m_selectedTracks->size() - 1)/2 - m_incomp.size();
2041 m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep, compSize );
2045 m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep,
count );
2049 m_hists[
"vertexYield"]->GetXaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2051 for(
auto&
vertex : *workVerticesContainer ) {
2052 auto ntrk =
vertex.selectedTrackIndices.size() +
vertex.associatedTrackIndices.size();
2053 if(
vertex.isGood && ntrk >= 2 ) {
2054 dynamic_cast<TH2F*
>( m_hists[
"vertexYieldNtrk"] )->Fill( ntrk, m_vertexingAlgorithmStep );
2058 m_hists[
"vertexYieldNtrk"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2059 m_hists[
"vertexYieldChi2"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2062 if( !
final )
return StatusCode::SUCCESS;
2064 for(
auto&
vertex : *workVerticesContainer ) {
2065 auto ntrk =
vertex.selectedTrackIndices.size() +
vertex.associatedTrackIndices.size();
2066 if(
vertex.isGood && ntrk >= 2 ) {
2067 m_hists[
"finalVtxNtrk"] ->Fill( ntrk );
2068 m_hists[
"finalVtxR"] ->Fill(
vertex.vertex.perp() );
2069 dynamic_cast<TH2F*
>( m_hists[
"finalVtxNtrkR"] )->Fill( ntrk,
vertex.vertex.perp() );
2073 return StatusCode::SUCCESS;
2078 std::vector<double>& impactParameters,
2079 std::vector<double>& impactParErrors){
2081 impactParameters.clear();
2082 impactParErrors.clear();
2084 if( m_jp.trkExtrapolator==1 ){
2085 m_fitSvc->VKalGetImpact(trk,
vertex,
static_cast<int>( trk->
charge() ), impactParameters, impactParErrors);
2087 else if( m_jp.trkExtrapolator==2 ){
2088 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(Gaudi::Hive::currentContext(), *trk,
vertex );
2089 if( !sv_perigee )
return false;
2090 impactParameters.push_back(sv_perigee->parameters() [
Trk::d0]);
2091 impactParameters.push_back(sv_perigee->parameters() [
Trk::z0]);
2092 impactParErrors.push_back((*sv_perigee->covariance())(
Trk::d0,
Trk::d0 ));
2093 impactParErrors.push_back((*sv_perigee->covariance())(
Trk::z0,
Trk::z0 ));
2096 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": Unknown track extrapolator " << m_jp.trkExtrapolator );