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 ) {
1071 m_decor_isAssociated.emplace (
"is_associated" + m_jp.augVerString );
1074 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": #verticess = " << workVerticesContainer->size() );
1076 unsigned associateCounter { 0 };
1079 for(
auto& wrkvrt : *workVerticesContainer ) {
1081 if( !wrkvrt.isGood )
continue;
1082 if( wrkvrt.selectedTrackIndices.size() <= 1 )
continue;
1084 improveVertexChi2( wrkvrt );
1086 wrkvrt.Chi2_core = wrkvrt.Chi2;
1088 auto& vertexPos = wrkvrt.vertex;
1090 std::vector<double> distanceToPVs;
1092 for(
const auto*
pv : *pvs ) {
1095 const auto& minDistance = *( std::min_element( distanceToPVs.begin(), distanceToPVs.end() ) );
1097 if( minDistance < m_jp.associateMinDistanceToPV )
continue;
1100 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertex pos = (" << vertexPos.x() <<
", " << vertexPos.y() <<
", " << vertexPos.z() <<
"), "
1101 "#selected = " << wrkvrt.selectedTrackIndices.size() <<
", #assoc = " << wrkvrt.associatedTrackIndices.size() );
1103 std::vector<const xAOD::TrackParticle*>
candidates;
1106 for(
auto itr = allTracks->
begin(); itr != allTracks->
end(); ++itr ) {
1107 const auto* trk = *itr;
1111 auto result = std::find_if( workVerticesContainer->begin(), workVerticesContainer->end(),
1113 auto found = std::find_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
1114 [&]( long int index ) {
1116 if (m_jp.doSelectTracksFromElectrons || m_jp.doSelectIDAndGSFTracks) {
1117 const xAOD::TrackParticle *id_tr;
1118 id_tr = xAOD::EgammaHelpers::getOriginalTrackParticleFromGSF(m_selectedTracks.at(index));
1119 return trk == m_selectedTracks.at(index) or trk == id_tr;
1122 return trk == m_selectedTracks.at(index);
1127 if(
result != workVerticesContainer->end() )
continue;
1132 auto result = std::find_if( m_associatedTracks.begin(), m_associatedTracks.end(),
1133 [&] (
const auto* atrk) { return trk == atrk; } );
1134 if(
result != m_associatedTracks.end() )
continue;
1141 if( trk->pt() < m_jp.associatePtCut )
continue;
1144 if( trk->chiSquared() / trk->numberDoF() > m_jp.associateChi2Cut )
continue;
1147 if( !checkTrackHitPatternToVertexOuterOnly( trk, vertexPos ) )
continue;
1150 std::vector<double> impactParameters;
1151 std::vector<double> impactParErrors;
1153 if( !getSVImpactParameters( trk, vertexPos, impactParameters, impactParErrors) )
continue;
1155 if( std::abs( impactParameters.at(0) ) / sqrt( impactParErrors.at(0) ) > m_jp.associateMaxD0Signif )
continue;
1156 if( std::abs( impactParameters.at(1) ) / sqrt( impactParErrors.at(1) ) > m_jp.associateMaxZ0Signif )
continue;
1159 <<
": d0 to vtx = " << impactParameters.at(k_d0)
1160 <<
", z0 to vtx = " << impactParameters.at(k_z0)
1161 <<
", distance to vtx = " << hypot( impactParameters.at(k_d0), impactParameters.at(k_z0) ) );
1169 std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
1173 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": attempting to associate track = " << trk );
1176 WrkVrt wrkvrt_backup = wrkvrt;
1178 m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
1180 std::vector<const xAOD::TrackParticle*> baseTracks;
1181 std::vector<const xAOD::NeutralParticle*> dummyNeutrals;
1185 for(
const auto&
index : wrkvrt.selectedTrackIndices ) {
1186 baseTracks.emplace_back( m_selectedTracks.at(
index ) );
1189 for(
const auto&
index : wrkvrt.associatedTrackIndices ) {
1190 baseTracks.emplace_back( m_associatedTracks.at(
index ) );
1194 baseTracks.emplace_back( trk );
1200 StatusCode sc = m_fitSvc->VKalVrtFitFast( baseTracks, initPos, *state );
1202 if(
sc.isFailure() )
ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": fast crude estimation failed.");
1204 const auto& diffPos = initPos - vertexPos;
1206 if( diffPos.norm() > 10. ) {
1208 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": approx vertex as original" );
1209 m_fitSvc->setApproximateVertex( vertexPos.x(), vertexPos.y(), vertexPos.z(), *state );
1213 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": approx vertex set to (" << initPos.x() <<
", " << initPos.y() <<
", " << initPos.z() <<
")" );
1214 m_fitSvc->setApproximateVertex( initPos.x(), initPos.y(), initPos.z(), *state );
1220 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": now vertex fitting..." );
1222 StatusCode sc = m_fitSvc->VKalVrtFit(baseTracks, dummyNeutrals,
1232 if(
sc.isFailure() ) {
1233 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": VKalVrtFit failure. Revert to backup");
1234 wrkvrt = wrkvrt_backup;
1236 if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 1 );
1242 if( m_jp.FillHist ) m_hists[
"associateMonitor"]->Fill( 0 );
1244 auto&
cov = wrkvrt.vertexCov;
1246 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": succeeded in associating. New vertex pos = (" << vertexPos.perp() <<
", " << vertexPos.z() <<
", " << vertexPos.perp()*vertexPos.phi() <<
")" );
1247 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) <<
")" );
1251 wrkvrt.associatedTrackIndices.emplace_back( m_associatedTracks.size() );
1253 m_associatedTracks.emplace_back( trk );
1254 (*m_decor_isAssociated)( *trk ) =
true;
1260 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1261 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": total associated number of tracks = " << associateCounter );
1262 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1264 return StatusCode::SUCCESS;
1269 StatusCode VrtSecInclusive::mergeByShuffling( std::vector<WrkVrt> *workVerticesContainer )
1272 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": #verticess = " << workVerticesContainer->size() );
1274 unsigned mergeCounter { 0 };
1277 std::sort( workVerticesContainer->begin(), workVerticesContainer->end(), [](
WrkVrt& v1,
WrkVrt&
v2) { return v1.selectedTrackIndices.size() < v2.selectedTrackIndices.size(); } );
1280 for(
auto& wrkvrt : *workVerticesContainer ) {
1281 if( !wrkvrt.isGood )
continue;
1282 if( wrkvrt.selectedTrackIndices.size() <= 1 )
continue;
1285 for(
auto ritr = workVerticesContainer->rbegin(); ritr != workVerticesContainer->rend(); ++ritr ) {
1286 auto& vertexToMerge = *ritr;
1288 if( !vertexToMerge.isGood )
continue;
1289 if( vertexToMerge.selectedTrackIndices.size() <= 1 )
continue;
1290 if( &wrkvrt == &vertexToMerge )
continue;
1291 if( vertexToMerge.selectedTrackIndices.size() < wrkvrt.selectedTrackIndices.size() )
continue;
1293 const double& significance = significanceBetweenVertices( wrkvrt, vertexToMerge );
1295 if( significance > m_jp.mergeByShufflingMaxSignificance )
continue;
1297 bool mergeFlag {
false };
1300 <<
": vertex " << &wrkvrt <<
" #tracks = " << wrkvrt.selectedTrackIndices.size()
1301 <<
" --> to Merge : " << &vertexToMerge <<
", #tracks = " << vertexToMerge.selectedTrackIndices.size()
1302 <<
" significance = " << significance );
1307 if( m_jp.doSuggestedRefitOnMerging && !mergeFlag ) {
1308 WrkVrt testVertex = wrkvrt;
1310 if(
sc.isFailure() ) {
1314 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1315 if( signif < min_signif ) min_signif = signif;
1317 if( signif < m_jp.mergeByShufflingAllowance ) {
1318 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method1: vertexToMerge " << &vertexToMerge <<
": test signif = " << signif );
1323 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif1"]->Fill( log10( min_signif ) );
1324 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE1 ); }
1329 if( m_jp.doMagnetMerging && !mergeFlag ) {
1332 for(
auto&
index : vertexToMerge.selectedTrackIndices ) {
1334 WrkVrt testVertex = wrkvrt;
1338 if(
sc.isFailure() ) {
1342 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1343 if( signif < min_signif ) min_signif = signif;
1345 if( signif < m_jp.mergeByShufflingAllowance ) {
1346 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method2: vertexToMerge " << &vertexToMerge <<
" track index " <<
index <<
": test signif = " << signif );
1353 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif2"]->Fill( log10( min_signif ) );
1355 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE2 ); }
1359 if( m_jp.doWildMerging && !mergeFlag ) {
1361 WrkVrt testVertex = wrkvrt;
1363 for(
auto&
index : vertexToMerge.selectedTrackIndices ) {
1368 if(
sc.isFailure() ) {
1372 const auto signif = significanceBetweenVertices( testVertex, vertexToMerge );
1373 if( signif < min_signif ) min_signif = signif;
1375 if( signif < m_jp.mergeByShufflingAllowance ) {
1376 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": method3: vertexToMerge " << &vertexToMerge <<
": test signif = " << signif );
1380 if( m_jp.FillHist && min_signif > 0. ) m_hists[
"shuffleMinSignif3"]->Fill( log10( min_signif ) );
1381 if( m_jp.FillHist && mergeFlag ) { m_hists[
"mergeType"]->Fill( SHUFFLE3 ); }
1388 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": vertexToMerge " << &vertexToMerge <<
" ==> min signif = " << min_signif <<
" judged to merge" );
1390 auto vertexToMerge_backup = vertexToMerge;
1391 auto wrkvrt_backup = wrkvrt;
1393 StatusCode sc = mergeVertices( vertexToMerge, wrkvrt );
1394 if(
sc.isFailure() ) {
1395 vertexToMerge = vertexToMerge_backup;
1396 wrkvrt = wrkvrt_backup;
1400 improveVertexChi2( wrkvrt );
1409 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1410 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Number of merges = " << mergeCounter );
1411 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1413 return StatusCode::SUCCESS;
1418 StatusCode VrtSecInclusive::mergeFinalVertices( std::vector<WrkVrt> *workVerticesContainer )
1421 unsigned mergeCounter { 0 };
1427 for(
auto& wrkvrt : *workVerticesContainer) {
1433 auto minDistance = findMinVerticesPair( workVerticesContainer, indexPair, &VrtSecInclusive::distanceBetweenVertices );
1439 auto& v1 = workVerticesContainer->at(indexPair.first);
1440 auto&
v2 = workVerticesContainer->at(indexPair.second);
1442 const double averageRadius = ( v1.vertex.perp() +
v2.vertex.perp() ) / 2.0;
1444 if( minDistance > m_jp.VertexMergeFinalDistCut + m_jp.VertexMergeFinalDistScaling * averageRadius ) {
1445 ATH_MSG_DEBUG(
"Vertices " << indexPair.first <<
" and " << indexPair.second
1446 <<
" are separated by distance " << minDistance );
1450 ATH_MSG_DEBUG(
"Merging FINAL vertices " << indexPair.first <<
" and " << indexPair.second
1451 <<
" which are separated by distance "<< minDistance );
1454 if(
sc.isFailure() ) {}
1455 if( m_jp.FillHist ) { m_hists[
"mergeType"]->Fill(
FINAL ); }
1457 improveVertexChi2( v1 );
1463 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1464 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Number of merges = " << mergeCounter );
1465 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
"----------------------------------------------" );
1467 return StatusCode::SUCCESS;
1474 StatusCode VrtSecInclusive::refitAndSelectGoodQualityVertices( std::vector<WrkVrt> *workVerticesContainer )
1484 ATH_CHECK( evtStore()->
retrieve( secondaryVertexContainer,
"VrtSecInclusive_" + m_jp.secondaryVerticesContainerName + m_jp.augVerString ) );
1489 enum { kPt, kEta, kPhi, kD0, kZ0, kErrP, kErrD0, kErrZ0, kChi2SV };
1490 if( m_trkDecors.empty() ) {
1501 if( !m_decor_is_svtrk_final ) {
1502 m_decor_is_svtrk_final.emplace (
"is_svtrk_final" + m_jp.augVerString );
1505 std::map<const WrkVrt*, const xAOD::Vertex*> wrkvrtLinkMap;
1508 const auto& ctx = Gaudi::Hive::currentContext();
1510 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": input #vertices = " << workVerticesContainer->size() );
1513 for(
auto& wrkvrt : *workVerticesContainer ) {
1515 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": candidate vertex: "
1516 <<
" isGood = " << (wrkvrt.isGood?
"true" :
"false")
1517 <<
", #ntrks = " << wrkvrt.nTracksTotal()
1518 <<
", #selectedTracks = " << wrkvrt.selectedTrackIndices.size()
1519 <<
", #associatedTracks = " << wrkvrt.associatedTrackIndices.size()
1521 <<
", (r, z) = (" << wrkvrt.vertex.perp()
1522 <<
", " << wrkvrt.vertex.z() <<
")" );
1524 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 0 );
1526 if( m_jp.removeFakeVrt && m_jp.removeFakeVrtLate ) {
1527 removeInconsistentTracks( wrkvrt );
1530 if( wrkvrt.nTracksTotal() < 2 ) {
1531 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": ntrk < 2 --> rejected." );
1535 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 1 );
1539 if( wrkvrt.vertex.perp() < 31.0 ) {
1542 wrkvrt.selectedTrackIndices.erase(
std::remove_if( wrkvrt.selectedTrackIndices.begin(), wrkvrt.selectedTrackIndices.end(),
1543 [&](
auto&
index ) {
1544 auto* trk = m_selectedTracks.at( index );
1548 wrkvrt.selectedTrackIndices.end() );
1551 wrkvrt.associatedTrackIndices.erase(
std::remove_if( wrkvrt.associatedTrackIndices.begin(), wrkvrt.associatedTrackIndices.end(),
1552 [&](
auto&
index ) {
1553 auto* trk = m_associatedTracks.at( index );
1557 wrkvrt.associatedTrackIndices.end() );
1565 if( m_jp.doFinalImproveChi2 ) {
1569 improveVertexChi2( wrkvrt );
1571 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1576 if( wrkvrt.nTracksTotal() < 2 )
continue;
1579 if( wrkvrt.selectedTrackIndices.size() < 2 )
continue;
1582 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 2 );
1589 if(
sc.isFailure() ) {
1591 auto indices = wrkvrt.associatedTrackIndices;
1593 wrkvrt.associatedTrackIndices.clear();
1594 sc = refitVertex( wrkvrt );
1595 if(
sc.isFailure() ) {
1596 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
1599 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1604 sc = refitVertex( wrkvrt );
1605 if(
sc.isFailure() || TMath::Prob( wrkvrt.Chi2, wrkvrt.ndof() ) < m_jp.improveChi2ProbThreshold ) {
1606 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": detected vertex fitting failure!" );
1613 if( wrkvrt.fitQuality() > backup.
fitQuality() ) wrkvrt = backup;
1617 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 3 );
1622 if( m_jp.FillNtuple ) m_ntupleVars->get<
unsigned int>(
"NumSecVrt" )++;
1624 TLorentzVector sumP4_pion;
1625 TLorentzVector sumP4_electron;
1626 TLorentzVector sumP4_proton;
1629 bool good_flag =
true;
1631 std::map<const std::deque<long int>*,
const std::vector<const xAOD::TrackParticle*>&> indicesSet
1633 { &(wrkvrt.selectedTrackIndices), m_selectedTracks },
1634 { &(wrkvrt.associatedTrackIndices), m_associatedTracks }
1637 for(
auto& pair : indicesSet ) {
1639 const auto*
indices = pair.first;
1640 const auto& tracks = pair.second;
1642 for(
const auto& itrk : *
indices ) {
1643 const auto* trk = tracks.at( itrk );
1644 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
1646 ATH_MSG_INFO(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Failed in obtaining the SV perigee!" );
1654 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": sv perigee could not be obtained --> rejected" );
1658 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 4 );
1661 std::vector<const xAOD::TrackParticle*> tracks;
1662 std::vector< std::pair<const xAOD::TrackParticle*, double> > trackChi2Pairs;
1666 for(
auto& pair : indicesSet ) {
1667 for(
const auto&
index : *pair.first ) tracks.emplace_back( pair.second.at(
index ) );
1670 auto trkitr = tracks.begin();
1671 auto chi2itr = wrkvrt.Chi2PerTrk.begin();
1673 for( ; ( trkitr!=tracks.end() && chi2itr!=wrkvrt.Chi2PerTrk.end() ); ++trkitr, ++chi2itr ) {
1674 trackChi2Pairs.emplace_back( *trkitr, *chi2itr );
1680 TLorentzVector sumP4_selected;
1682 bool badIPflag {
false };
1685 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Track loop: size = " << tracks.size() );
1686 for(
auto& pair : trackChi2Pairs ) {
1688 const auto* trk = pair.first;
1689 const auto& chi2AtSV = pair.second;
1691 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": start." );
1694 fillTrackSummary( trk_summary, trk );
1700 double trk_pt = trk->pt();
1701 double trk_eta = trk->eta();
1702 double trk_phi = trk->phi();
1704 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": in vrt chg/pt/phi/eta = "
1705 << trk->charge() <<
","
1712 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Get the prigee of the track at the vertex." );
1714 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(ctx, *trk, wrkvrt.vertex );
1716 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": Failed in obtaining the SV perigee!" );
1718 for(
auto& pair : m_trkDecors ) {
1721 (*m_decor_is_svtrk_final)( *trk ) =
true;
1725 double qOverP_wrtSV = sv_perigee->parameters() [
Trk::qOverP];
1726 double theta_wrtSV = sv_perigee->parameters() [
Trk::theta];
1727 double p_wrtSV = 1.0 / std::abs( qOverP_wrtSV );
1728 double pt_wrtSV = p_wrtSV *
sin( theta_wrtSV );
1729 double eta_wrtSV = -
log(
tan( theta_wrtSV/2. ) );
1730 double phi_wrtSV = sv_perigee->parameters() [
Trk::phi];
1731 double d0_wrtSV = sv_perigee->parameters() [
Trk::d0];
1732 double z0_wrtSV = sv_perigee->parameters() [
Trk::z0];
1733 double errd0_wrtSV = (*sv_perigee->covariance())(
Trk::d0,
Trk::d0 );
1734 double errz0_wrtSV = (*sv_perigee->covariance())(
Trk::z0,
Trk::z0 );
1738 ( m_trkDecors.at(kPt) )( *trk ) = pt_wrtSV;
1739 ( m_trkDecors.at(kEta) )( *trk ) = eta_wrtSV;
1740 ( m_trkDecors.at(kPhi) )( *trk ) = phi_wrtSV;
1741 ( m_trkDecors.at(kD0) )( *trk ) = d0_wrtSV;
1742 ( m_trkDecors.at(kZ0) )( *trk ) = z0_wrtSV;
1743 ( m_trkDecors.at(kErrP) )( *trk ) = errP_wrtSV;
1744 ( m_trkDecors.at(kErrD0) )( *trk ) = errd0_wrtSV;
1745 ( m_trkDecors.at(kErrZ0) )( *trk ) = errz0_wrtSV;
1746 ( m_trkDecors.at(kChi2SV))( *trk ) = chi2AtSV;
1748 (*m_decor_is_svtrk_final)( *trk ) =
true;
1750 TLorentzVector p4wrtSV_pion;
1751 TLorentzVector p4wrtSV_electron;
1752 TLorentzVector p4wrtSV_proton;
1760 if( !is_associatedAcc(*trk) ) {
1761 sumP4_selected += p4wrtSV_pion;
1764 sumP4_selected += p4wrtSV_pion;
1767 sumP4_pion += p4wrtSV_pion;
1768 sumP4_electron += p4wrtSV_electron;
1769 sumP4_proton += p4wrtSV_proton;
1771 ATH_MSG_VERBOSE(
" > " << __FUNCTION__ <<
": > Track index " << trk->index() <<
": end." );
1776 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Final Sec.Vertex=" << wrkvrt.nTracksTotal() <<
", "
1777 <<wrkvrt.vertex.perp() <<
", "<<wrkvrt.vertex.z() <<
", "
1778 <<wrkvrt.vertex.phi() <<
", mass = "<< sumP4_pion.M() <<
"," << sumP4_electron.M() );
1785 std::vector<double> opAngles;
1787 for(
auto itr1 = tracks.begin(); itr1 != tracks.end(); ++itr1 ) {
1788 for(
auto itr2 =
std::next( itr1 ); itr2 != tracks.end(); ++itr2 ) {
1789 const auto&
p1 = (*itr1)->p4().Vect();
1790 const auto&
p2 = (*itr2)->p4().Vect();
1792 opAngles.emplace_back(
cos );
1795 minOpAng = *( std::max_element( opAngles.begin(), opAngles.end() ) );
1796 if( m_jp.FillNtuple ) m_ntupleVars->get< vector<double> >(
"SecVtx_MinOpAng" ).emplace_back(minOpAng);
1799 if( m_jp.FillHist ) m_hists[
"finalCutMonitor"]->Fill( 5 );
1802 ATH_MSG_DEBUG(
" > " << __FUNCTION__ <<
": Bad impact parameter signif wrt SV was flagged." );
1805 if (m_jp.doRemoveNonLeptonVertices) {
1807 bool oneLepMatchTrack =
false;
1808 for (
const auto *trk: tracks) {
1809 if (
std::find(m_leptonicTracks.begin(), m_leptonicTracks.end(), trk) != m_leptonicTracks.end() ) {
1810 oneLepMatchTrack =
true;
1816 if (!oneLepMatchTrack)
continue;
1822 wrkvrt.isGood =
true;
1827 secondaryVertexContainer->emplace_back(
vertex );
1830 vertex->setPosition( wrkvrt.vertex );
1837 vertex->setFitQuality( wrkvrt.Chi2_core, wrkvrt.ndof_core() );
1840 std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
1841 vertex->setCovariance(fCov);
1862 vtx_pxAcc(*
vertex) = wrkvrt.vertexMom.Px();
1863 vtx_pyAcc(*
vertex) = wrkvrt.vertexMom.Py();
1864 vtx_pzAcc(*
vertex) = wrkvrt.vertexMom.Pz();
1866 vtx_massAcc(*
vertex) = wrkvrt.vertexMom.M();
1867 vtx_chargeAcc(*
vertex) = wrkvrt.Charge;
1869 chi2_coreAcc(*
vertex) = wrkvrt.Chi2_core;
1870 ndof_coreAcc(*
vertex) = wrkvrt.ndof_core();
1871 chi2_assocAcc(*
vertex) = wrkvrt.Chi2;
1872 ndof_assocAcc(*
vertex) = wrkvrt.ndof();
1874 massAcc(*
vertex) = sumP4_pion.M();
1875 mass_eAcc(*
vertex) = sumP4_electron.M();
1876 mass_selectedTracksAcc(*
vertex) = sumP4_selected.M();
1877 minOpAngAcc(*
vertex) = minOpAng;
1878 num_trksAcc(*
vertex) = wrkvrt.nTracksTotal();
1879 num_selectedTracksAcc(*
vertex) = wrkvrt.selectedTrackIndices.size();
1880 num_associatedTracksAcc(*
vertex) = wrkvrt.associatedTrackIndices.size();
1881 dCloseVrtAcc(*
vertex) = wrkvrt.closestWrkVrtValue;
1885 for(
auto trk_id : wrkvrt.selectedTrackIndices ) {
1893 vertex->addTrackAtVertex( link_trk, 1. );
1897 for(
auto trk_id : wrkvrt.associatedTrackIndices ) {
1905 vertex->addTrackAtVertex( link_trk, 1. );
1910 if( m_jp.doMapToLocal ) {
1918 if( mappedVtx.
valid ) {
1936 if( m_jp.doTruth ) {
1941 wrkvrtLinkMap[&wrkvrt] =
vertex;
1946 if( m_jp.FillNtuple ) {
1947 ATH_CHECK( fillAANT_SecondaryVertices( secondaryVertexContainer ) );
1952 if( m_jp.doAugmentDVimpactParametersToMuons ) {
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Muon> (
"Muons" ) ); }
1953 if( m_jp.doAugmentDVimpactParametersToElectrons ) {
ATH_CHECK( augmentDVimpactParametersToLeptons<xAOD::Electron>(
"Electrons" ) ); }
1955 }
catch (
const std::out_of_range&
e) {
1957 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": out of range error is detected: " <<
e.what() );
1959 return StatusCode::SUCCESS;
1963 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": some other error is detected." );
1965 return StatusCode::SUCCESS;
1969 return StatusCode::SUCCESS;
1974 StatusCode VrtSecInclusive::monitorVertexingAlgorithmStep( std::vector<WrkVrt>* workVerticesContainer,
const std::string&
name,
bool final ) {
1976 if( m_jp.FillIntermediateVertices ) {
1983 ATH_CHECK( evtStore()->
retrieve( intermediateVertexContainer,
"VrtSecInclusive_IntermediateVertices_" +
name + m_jp.augVerString ) );
1985 for(
auto& wrkvrt : *workVerticesContainer ) {
1988 intermediateVertexContainer->emplace_back(
vertex );
1991 vertex->setPosition( wrkvrt.vertex );
1997 int ndof = wrkvrt.ndof();
2001 std::vector<float> fCov(wrkvrt.vertexCov.cbegin(), wrkvrt.vertexCov.cend());
2002 vertex->setCovariance(fCov);
2006 for(
auto trk_id : wrkvrt.selectedTrackIndices ) {
2014 vertex->addTrackAtVertex( link_trk, 1. );
2018 for(
auto trk_id : wrkvrt.associatedTrackIndices ) {
2026 vertex->addTrackAtVertex( link_trk, 1. );
2035 if( !m_jp.FillHist )
return StatusCode::SUCCESS;
2037 printWrkSet( workVerticesContainer, Form(
"%s (step %u)",
name.c_str(), m_vertexingAlgorithmStep) );
2039 unsigned count = std::count_if( workVerticesContainer->begin(), workVerticesContainer->end(),
2040 [](
WrkVrt&
v ) { return ( v.selectedTrackIndices.size() + v.associatedTrackIndices.size() ) >= 2; } );
2042 if( m_vertexingAlgorithmStep == 0 ) {
2044 const auto compSize = m_selectedTracks.size()*(m_selectedTracks.size() - 1)/2 - m_incomp.size();
2045 m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep, compSize );
2049 m_hists[
"vertexYield"]->Fill( m_vertexingAlgorithmStep,
count );
2053 m_hists[
"vertexYield"]->GetXaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2055 for(
auto&
vertex : *workVerticesContainer ) {
2056 auto ntrk =
vertex.selectedTrackIndices.size() +
vertex.associatedTrackIndices.size();
2057 if(
vertex.isGood && ntrk >= 2 ) {
2058 dynamic_cast<TH2F*
>( m_hists[
"vertexYieldNtrk"] )->Fill( ntrk, m_vertexingAlgorithmStep );
2062 m_hists[
"vertexYieldNtrk"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2063 m_hists[
"vertexYieldChi2"]->GetYaxis()->SetBinLabel( m_vertexingAlgorithmStep+1,
name.c_str() );
2066 if( !
final )
return StatusCode::SUCCESS;
2068 for(
auto&
vertex : *workVerticesContainer ) {
2069 auto ntrk =
vertex.selectedTrackIndices.size() +
vertex.associatedTrackIndices.size();
2070 if(
vertex.isGood && ntrk >= 2 ) {
2071 m_hists[
"finalVtxNtrk"] ->Fill( ntrk );
2072 m_hists[
"finalVtxR"] ->Fill(
vertex.vertex.perp() );
2073 dynamic_cast<TH2F*
>( m_hists[
"finalVtxNtrkR"] )->Fill( ntrk,
vertex.vertex.perp() );
2077 return StatusCode::SUCCESS;
2082 std::vector<double>& impactParameters,
2083 std::vector<double>& impactParErrors){
2085 impactParameters.clear();
2086 impactParErrors.clear();
2088 if( m_jp.trkExtrapolator==1 ){
2089 m_fitSvc->VKalGetImpact(trk,
vertex,
static_cast<int>( trk->
charge() ), impactParameters, impactParErrors);
2091 else if( m_jp.trkExtrapolator==2 ){
2092 auto sv_perigee = m_trackToVertexTool->perigeeAtVertex(Gaudi::Hive::currentContext(), *trk,
vertex );
2093 if( !sv_perigee )
return false;
2094 impactParameters.push_back(sv_perigee->parameters() [
Trk::d0]);
2095 impactParameters.push_back(sv_perigee->parameters() [
Trk::z0]);
2096 impactParErrors.push_back((*sv_perigee->covariance())(
Trk::d0,
Trk::d0 ));
2097 impactParErrors.push_back((*sv_perigee->covariance())(
Trk::z0,
Trk::z0 ));
2100 ATH_MSG_WARNING(
" > " << __FUNCTION__ <<
": Unknown track extrapolator " << m_jp.trkExtrapolator );