From d5754e97ee99a7d59e2bda483acee523becaf329 Mon Sep 17 00:00:00 2001
From: Hideyuki Oide <Hideyuki.Oide@cern.ch>
Date: Thu, 21 Sep 2017 15:37:12 +0200
Subject: [PATCH] VrtSecInclusive:  extrapolation option algorithm was built,
 but having significant memory leak

---
 .../VrtSecInclusive/VrtSecInclusive.h         |  43 +-
 .../VKalVrt/VrtSecInclusive/cmt/requirements  |   2 +
 .../src/TrackSelectionAlgs.cxx                |  10 +-
 .../VKalVrt/VrtSecInclusive/src/Utilities.cxx | 684 ++++++++++++------
 .../VrtSecInclusive/src/VertexingAlgs.cxx     |   7 +-
 .../VrtSecInclusive/src/VrtSecInclusive.cxx   |  19 +-
 6 files changed, 515 insertions(+), 250 deletions(-)

diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h b/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h
index f9a0e6de02f9..82e683e7d3ce 100755
--- a/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h
@@ -31,8 +31,13 @@
 #include "ITrackToVertex/ITrackToVertex.h"
 #include "TrkVertexFitterInterfaces/ITrackToVertexIPEstimator.h"
 #include "TrkExInterfaces/IExtrapolator.h"
+#include "TrkExInterfaces/IExtrapolationEngine.h"
 #include "TrkSurfaces/CylinderSurface.h"
 #include "TrkDetDescrInterfaces/IVertexMapper.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "InDetConditionsSummaryService/IInDetConditionsSvc.h"
+#include "InDetIdentifier/PixelID.h"
+#include "InDetIdentifier/SCT_ID.h"
 
 // xAOD Classes
 #include "xAODEventInfo/EventInfo.h"
@@ -196,6 +201,19 @@ namespace VKalVrtAthena {
     ToolHandle<Trk::ITrackToVertexIPEstimator> m_trackToVertexIPEstimatorTool;
     ToolHandle<Trk::IExtrapolator> m_extrapolator;
     ToolHandle<Trk::IVertexMapper> m_vertexMapper;
+    ToolHandle<Trk::IExtrapolationEngine> m_extrapolationEngine;
+    
+    /** Condition service **/
+    ServiceHandle <IInDetConditionsSvc> m_pixelCondSummarySvc;
+    ServiceHandle <IInDetConditionsSvc> m_sctCondSummarySvc;
+    
+    const AtlasDetectorID* m_atlasId;
+    const PixelID* m_pixelId;
+    const SCT_ID*  m_sctId;
+    
+    std::string m_checkPatternStrategy;
+    using PatternStrategyFunc = bool (VrtSecInclusive::*) ( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex );
+    std::map<std::string, PatternStrategyFunc> m_patternStrategyFuncs;
     
     // Histograms for stats
     TH1D* m_hb_massPiPi;
@@ -257,6 +275,13 @@ namespace VKalVrtAthena {
     };
     
     
+    using Detector = int;
+    using Bec      = int;
+    using Layer    = int;
+    using Flag     = int;
+    using ExtrapolatedPoint   = std::tuple<const TVector3, Detector, Bec, Layer, Flag>;
+    using ExtrapolatedPattern = std::vector< ExtrapolatedPoint >;
+    
     ////////////////////////////////////////////////////////////////////////////////////////
     // 
     // Vertexing Algorithm Tool Member Functions
@@ -342,9 +367,21 @@ namespace VKalVrtAthena {
     } track_summary;
    
     void fillTrackSummary( track_summary& summary, const xAOD::TrackParticle *trk );
-    bool passedFakeReject( const Amg::Vector3D& FitVertex, const xAOD::TrackParticle *itrk, const xAOD::TrackParticle *jtrk );
-    bool checkTrackHitPatternToVertex( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex );
+    
+    ExtrapolatedPattern* extrapolatedPattern( const xAOD::TrackParticle* );
    
+    /* A classical method with hard-coded geometry */
+    bool checkTrackHitPatternToVertex( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex );
+    
+    /* New method with track extrapolation */
+    bool checkTrackHitPatternToVertexByExtrapolation( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex );
+    
+    /* A classical method with hard-coded geometry */
+    bool passedFakeReject( const Amg::Vector3D& FitVertex, const xAOD::TrackParticle *itrk, const xAOD::TrackParticle *jtrk );
+    
+    /* New method with track extrapolation */
+    bool passedFakeRejectByExtrapolation( const Amg::Vector3D& FitVertex, const xAOD::TrackParticle *itrk, const xAOD::TrackParticle *jtrk );
+    
     ////////////////////////////////////////////////////////////////////////////////////////
     // 
     // Truth Information Algorithms Member Functions
@@ -354,8 +391,6 @@ namespace VKalVrtAthena {
     // new version of truth routine - MCEventCollection (GEN_AOD or TruthEvent (ESD)
     StatusCode getNewTruthInfo();
     
-    //
-    //HepMC::GenParticle *getTrkGenParticle(const xAOD::TrackParticle*, double& matchProb);
     const xAOD::TruthParticle *getTrkGenParticle(const xAOD::TrackParticle* /*, double& matchProb*/) const;
     
     
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/cmt/requirements b/Reconstruction/VKalVrt/VrtSecInclusive/cmt/requirements
index 9a0d613b118c..769bb60fab5e 100755
--- a/Reconstruction/VKalVrt/VrtSecInclusive/cmt/requirements
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/cmt/requirements
@@ -19,6 +19,8 @@ use TrkExInterfaces           TrkExInterfaces-*           Tracking/TrkExtrapolat
 use TrkSurfaces               TrkSurfaces-*               Tracking/TrkDetDescr
 use TrkDetDescrInterfaces     TrkDetDescrInterfaces-*     Tracking/TrkDetDescr
 use ITrackToVertex            ITrackToVertex-*            Reconstruction/RecoTools
+use InDetConditionsSummaryService  InDetConditionsSummaryService*  InnerDetector/InDetConditions
+use InDetIdentifier           InDetIdentifier-*           InnerDetector/InDetDetDescr
 use xAODEventInfo             xAODEventInfo-*             Event/xAOD
 use xAODTracking              xAODTracking-*              Event/xAOD
 use xAODTruth                 xAODTruth-*                 Event/xAOD
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/TrackSelectionAlgs.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/TrackSelectionAlgs.cxx
index bd25006df91f..573e6553152c 100644
--- a/Reconstruction/VKalVrt/VrtSecInclusive/src/TrackSelectionAlgs.cxx
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/TrackSelectionAlgs.cxx
@@ -42,10 +42,6 @@ namespace VKalVrtAthena {
     
     if( m_FillHist ) m_trkSelCuts->Fill(1.); 
     
-    //ATH_MSG_VERBOSE("here:0 ");
-    
-    unsigned n = 0;
-    
     for( auto *trk : *trackParticleContainer ) {
       
       //trk->auxdecor<bool>("is_selected") = false;
@@ -70,9 +66,9 @@ namespace VKalVrtAthena {
       if( !(trk->summaryValue( TRTHits,   xAOD::numberOfTRTHits                 ) ) ) TRTHits   =0;
       long int SharedHits = PixShare + SctShare;
       
-      double theta  = trk->theta();
-      double qOverP = trk->qOverP();
-      double ptrk   = (1./qOverP);
+      //double theta  = trk->theta();
+      //double qOverP = trk->qOverP();
+      //double ptrk   = (1./qOverP);
       double pT     = trk->pt();
       double trketa = trk->eta();
       double chi2   = trk->chiSquared() / trk->numberDoF();
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx
index 4f2c7238b2f7..dfa59942f710 100644
--- a/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx
@@ -594,8 +594,12 @@ namespace VKalVrtAthena {
 
     declareProperty("VertexFitterTool",             m_fitSvc, " Private TrkVKalVrtFitter"           );
     declareProperty("Extrapolator",                 m_extrapolator                                  );
+    declareProperty("ExtrapolationEngine",          m_extrapolationEngine                           );
     declareProperty("VertexMapper",                 m_vertexMapper                                  );
+    declareProperty("PixelConditionsSummarySvc",    m_pixelCondSummarySvc                           );
+    declareProperty("SCT_ConditionsSummarySvc",     m_sctCondSummarySvc                             );
     
+    declareProperty("CheckHitPatternStrategy",      m_checkPatternStrategy = "Classical"            ); // Either Classical or Extrapolation
   }
   
   
@@ -792,17 +796,219 @@ namespace VKalVrtAthena {
   }
   
   
+  
   //____________________________________________________________________________________________________
-  bool VrtSecInclusive::passedFakeReject( const Amg::Vector3D& FitVertex,
-					  const xAOD::TrackParticle *itrk,
-					  const xAOD::TrackParticle *jtrk  )
+  VrtSecInclusive::ExtrapolatedPattern* VrtSecInclusive::extrapolatedPattern( const xAOD::TrackParticle* trk ) {
+    
+    auto* pattern = new ExtrapolatedPattern;
+    
+    Trk::ExtrapolationCell < Trk::TrackParameters > ecc( trk->perigeeParameters() );
+    ecc.setParticleHypothesis( Trk::ParticleHypothesis::pion );
+    ecc.addConfigurationMode(Trk::ExtrapolationMode::StopAtBoundary);   // stop at the next ID / Calo / MS boundary
+    ecc.addConfigurationMode(Trk::ExtrapolationMode::FATRAS);           // force initial radialDirection to be outward
+    ecc.addConfigurationMode(Trk::ExtrapolationMode::CollectSensitive); // collect parameters on sensitive elements
+    
+    auto eCode = m_extrapolationEngine->extrapolate(ecc);
+    
+    if( !eCode.isSuccess() ) { 
+      ecc.emptyGarbageBin( eCode );
+      return pattern;
+    }
+    
+    for (auto& es : ecc.extrapolationSteps) {
+      const auto* parameters = es.parameters;
+      
+      const TVector3 position( parameters->position().x(), parameters->position().y(), parameters->position().z() );
+      
+      const auto* detElement = parameters->associatedSurface().associatedDetectorElement();
+      
+      if( detElement ) {
+        
+        enum { Pixel = 1, SCT = 2 };
+        
+        const auto& id = detElement->identify();
+        Flag active = false;
+        
+        if( m_atlasId->is_pixel(id) ) {
+          
+          auto idHash = m_pixelId->wafer_hash( id );
+          active = m_pixelCondSummarySvc->isActive( idHash );
+          
+          pattern->emplace_back( std::make_tuple( position, Pixel, m_pixelId->barrel_ec(id), m_pixelId->layer_disk(id), active ) );
+          
+        } else if( m_atlasId->is_sct(id) ) {
+          
+          auto idHash = m_sctId->wafer_hash( id );
+          active = m_sctCondSummarySvc->isActive( idHash );
+          
+          pattern->emplace_back( std::make_tuple( position, SCT, m_sctId->barrel_ec(id), m_sctId->layer_disk(id), active ) );
+          
+        }
+        
+        ATH_MSG_VERBOSE(" >> " << __FUNCTION__ << ", track " << trk << ": position = (" << position.x() << ", " << position.y() << ", " << position.z() << "), detElement ID = " << id << ", active = " << active
+                     << ": (det, bec, layer) = (" << std::get<1>( pattern->back() ) << ", " << std::get<2>( pattern->back() ) << ", "  << std::get<3>( pattern->back() ) << ")" );
+        
+      }
+      
+      // Stressfully, user needs to explicitly care of the memory management :(
+      delete parameters;
+      delete es.transportJacobian;
+    }
+    
+    // Stressfully, user needs to explicitly care of the memory management :(
+    if( ecc.endParameters )          delete ecc.endParameters;
+    if( ecc.leadParameters )         delete ecc.leadParameters;
+    if( ecc.eLoss )                  delete ecc.eLoss;
+    
+    ecc.emptyGarbageBin( eCode );
+    
+    return pattern;
+  }
+  
+  
+  //____________________________________________________________________________________________________
+  bool VrtSecInclusive::checkTrackHitPatternToVertexByExtrapolation( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex )
   {
     
-    const double rad  = sqrt(FitVertex.x()*FitVertex.x() + FitVertex.y()*FitVertex.y()); 
-    const double absz = fabs( FitVertex.z() );
+    std::unique_ptr<ExtrapolatedPattern> exPattern( extrapolatedPattern( trk ) );
     
-    const uint32_t pattern_itrk = itrk->hitPattern();
-    const uint32_t pattern_jtrk = jtrk->hitPattern();
+    using LayerCombination = std::vector<int>;
+    
+    static std::map<LayerCombination, unsigned> layerMap;
+    if( layerMap.size() == 0 ) {
+      layerMap[ { 1, 0, 0 } ] = Trk::pixelBarrel0;
+      layerMap[ { 1, 0, 1 } ] = Trk::pixelBarrel1;
+      layerMap[ { 1, 0, 2 } ] = Trk::pixelBarrel2;
+      layerMap[ { 1, 0, 3 } ] = Trk::pixelBarrel3;
+      
+      layerMap[ { 1, 2, 0 } ] = Trk::pixelEndCap0;
+      layerMap[ { 1, 2, 1 } ] = Trk::pixelEndCap1;
+      layerMap[ { 1, 2, 2 } ] = Trk::pixelEndCap2;
+      layerMap[ { 1,-2, 0 } ] = Trk::pixelEndCap0;
+      layerMap[ { 1,-2, 1 } ] = Trk::pixelEndCap1;
+      layerMap[ { 1,-2, 2 } ] = Trk::pixelEndCap2;
+      
+      layerMap[ { 2, 0, 0 } ] = Trk::sctBarrel0;
+      layerMap[ { 2, 0, 1 } ] = Trk::sctBarrel1;
+      layerMap[ { 2, 0, 2 } ] = Trk::sctBarrel2;
+      layerMap[ { 2, 0, 3 } ] = Trk::sctBarrel3;
+
+      layerMap[ { 2, 2, 0 } ] = Trk::sctEndCap0;
+      layerMap[ { 2, 2, 1 } ] = Trk::sctEndCap1;
+      layerMap[ { 2, 2, 2 } ] = Trk::sctEndCap2;
+      layerMap[ { 2, 2, 3 } ] = Trk::sctEndCap3;
+      layerMap[ { 2, 2, 4 } ] = Trk::sctEndCap4;
+      layerMap[ { 2, 2, 5 } ] = Trk::sctEndCap5;
+      layerMap[ { 2, 2, 6 } ] = Trk::sctEndCap6;
+      layerMap[ { 2, 2, 7 } ] = Trk::sctEndCap7;
+      layerMap[ { 2, 2, 8 } ] = Trk::sctEndCap8;
+      layerMap[ { 2,-2, 0 } ] = Trk::sctEndCap0;
+      layerMap[ { 2,-2, 1 } ] = Trk::sctEndCap1;
+      layerMap[ { 2,-2, 2 } ] = Trk::sctEndCap2;
+      layerMap[ { 2,-2, 3 } ] = Trk::sctEndCap3;
+      layerMap[ { 2,-2, 4 } ] = Trk::sctEndCap4;
+      layerMap[ { 2,-2, 5 } ] = Trk::sctEndCap5;
+      layerMap[ { 2,-2, 6 } ] = Trk::sctEndCap6;
+      layerMap[ { 2,-2, 7 } ] = Trk::sctEndCap7;
+      layerMap[ { 2,-2, 8 } ] = Trk::sctEndCap8;
+    }
+    
+    enum { position=0, detector=1, bec=2, layer=3, isActive=4 };
+    
+    static const unsigned INVALID = 9999;
+    
+    // Labmda!
+    auto getDetectorType = [&]( const ExtrapolatedPoint& point ) -> unsigned {
+      
+      const LayerCombination comb { std::get<detector>( point ), std::get<bec>( point ), std::get<layer>( point ) };
+      
+      for( auto& pair : layerMap ) {
+        if( pair.first == comb ) {
+          return pair.second;
+        }
+      }
+      
+      return INVALID;
+    };
+    
+    uint32_t expectedHitPattern { 0 };
+    
+    // Loop over extrapolated points
+    for( auto itr = exPattern->begin(); itr != exPattern->end(); ++itr ) {
+      if( std::next( itr ) == exPattern->end() ) continue;
+      
+      const auto& point      = *itr;
+      const auto& nextPoint  = *( std::next( itr ) );
+      
+      ATH_MSG_DEBUG( " > " <<  __FUNCTION__ << ": isActive = " << std::get<isActive>( point ) );
+      
+      // if the front-end module is not active, then the hit is not expected.
+      if( false == std::get<isActive>( point ) ) continue;
+      
+      auto sectionVector = std::get<position>( nextPoint ) - std::get<position>( point );
+      auto vertexVector  = TVector3( vertex.x(), vertex.y(), vertex.z() ) - std::get<position>( point );
+      
+      // if the inner product of the above two vectors is positive,
+      // then point is inner than the vertex.
+      // Else, the point is outer than the vertex and expect to have hits
+      // when the track is originated from the vertex.
+      
+      ATH_MSG_DEBUG( " > " <<  __FUNCTION__ << ": sectionVector = (" << sectionVector.x() << ", " << sectionVector.y() << ", " << sectionVector.z() << ")" );
+      ATH_MSG_DEBUG( " > " <<  __FUNCTION__ << ": vertexVector = (" << vertexVector.x() << ", " << vertexVector.y() << ", " << vertexVector.z() << ")" );
+      ATH_MSG_DEBUG( " > " <<  __FUNCTION__ << ": cosTheta( sectionVector, vertexVector)  = " << sectionVector * vertexVector / sectionVector.Mag() / vertexVector.Mag() );
+      
+      if( sectionVector * vertexVector > 0. ) continue;
+      
+      // now, the hit is expected to present.
+      
+      const auto& detectorType = getDetectorType( point );
+      
+      ATH_MSG_DEBUG( " > " <<  __FUNCTION__ << ": detType = " << detectorType );
+      
+      if( detectorType == INVALID ) continue;
+      
+      if( ! (expectedHitPattern & (1 << detectorType)) ) {
+        expectedHitPattern += ( 1 << detectorType );
+      }
+    }
+    
+    std::string msg = "Expected hit pattern: ";
+    for( unsigned i=0; i<Trk::numberOfDetectorTypes; i++) {
+      msg += Form("%u", ( expectedHitPattern >> i ) & 1 );
+    }
+    ATH_MSG_DEBUG( " > " << __FUNCTION__ << ": " << msg );
+    
+    msg = "Recorded hit pattern: ";
+    for( unsigned i=0; i<Trk::numberOfDetectorTypes; i++) {
+      msg += Form("%u", ( trk->hitPattern() >> i ) & 1 );
+    }
+    ATH_MSG_DEBUG( " > " << __FUNCTION__ << ": " << msg );
+    
+    exPattern->clear();
+    
+    return ( expectedHitPattern == trk->hitPattern() );
+  }
+    
+
+  //____________________________________________________________________________________________________
+  bool VrtSecInclusive::passedFakeRejectByExtrapolation( const Amg::Vector3D& FitVertex,
+                                                         const xAOD::TrackParticle *itrk,
+                                                         const xAOD::TrackParticle *jtrk  )
+  {
+    const bool check_itrk = checkTrackHitPatternToVertexByExtrapolation( itrk, FitVertex );
+    const bool check_jtrk = checkTrackHitPatternToVertexByExtrapolation( jtrk, FitVertex );
+    return ( check_itrk && check_jtrk );
+  }
+  
+  
+  //____________________________________________________________________________________________________
+  bool VrtSecInclusive::checkTrackHitPatternToVertex( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex )
+  {
+    
+    const double rad  = vertex.perp();
+    const double absz = fabs( vertex.z() );
+    
+    const uint32_t pattern = trk->hitPattern();
     
 	
     if( m_geoModel == VKalVrtAthena::GeoModel::Run2 ) {
@@ -886,155 +1092,112 @@ namespace VKalVrtAthena {
       //////////////////////////////////////////////////////////////////////////////////
       if( vertex_pattern == insideBeamPipe ) {
 	
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel0)) ) return false;
 	
 	
       } else if( vertex_pattern == insidePixelBarrel0 ) {
 	
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel0 ) {
 	
 	// require nothing for PixelBarrel0
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel0_and_insidePixelBarrel1 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel1 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
 	// require nothing for PixelBarrel1
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel1_and_insidePixelBarrel2 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel2 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
 	// require nothing for PixelBarrel2
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
       }
       
 
       else if( vertex_pattern == outsidePixelBarrel2_and_insidePixelBarrel3 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
       }
 	
       else if( vertex_pattern == aroundPixelBarrel3 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
 	// require nothing for PixelBarrel3
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel3_and_insideSctBarrel0 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel0 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
 	// require nothing for SctBarrel0
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsideSctBarrel0_and_insideSctBarrel1 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel1 ) {
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
 	// require nothing for SctBarrel1
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel2)) ) return false;
       }
       //////////////////////////////////////////////////////////////////////////////////
       
@@ -1113,122 +1276,91 @@ namespace VKalVrtAthena {
       //////////////////////////////////////////////////////////////////////////////////
       if( vertex_pattern == insideBeamPipe ) {
 	
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
 	
       }
       
       
       else if( vertex_pattern == insidePixelBarrel1 ) {
 	
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel1 ) {
 	
 	// require nothing for PixelBarrel1
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel1_and_insidePixelBarrel2 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel2 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
 	// require nothing for PixelBarrel2
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
       }
       
 
       else if( vertex_pattern == outsidePixelBarrel2_and_insidePixelBarrel3 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
       }
 	
       else if( vertex_pattern == aroundPixelBarrel3 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
 	// require nothing for PixelBarrel3
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel3_and_insideSctBarrel0 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel0 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
 	// require nothing for SctBarrel0
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsideSctBarrel0_and_insideSctBarrel1 ) {
 	
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel1 ) {
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
-	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
 	// require nothing for SctBarrel1
-	if( ! (pattern_itrk & (1<<Trk::sctBarrel2)) ) return false;
-	if( ! (pattern_jtrk & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern & (1<<Trk::sctBarrel2)) ) return false;
       }
       //////////////////////////////////////////////////////////////////////////////////
       
@@ -1239,16 +1371,24 @@ namespace VKalVrtAthena {
     return true;
   }
   
-  
 
   //____________________________________________________________________________________________________
-  bool VrtSecInclusive::checkTrackHitPatternToVertex( const xAOD::TrackParticle *trk, const Amg::Vector3D& vertex )
+  bool VrtSecInclusive::passedFakeReject( const Amg::Vector3D& FitVertex,
+					  const xAOD::TrackParticle *itrk,
+					  const xAOD::TrackParticle *jtrk  )
   {
     
-    const double rad  = hypot( vertex.x(), vertex.y() );
-    const double absz = fabs( vertex.z() );
+    const bool& check_itrk = ( this->*m_patternStrategyFuncs[m_checkPatternStrategy] )( itrk, FitVertex );
+    const bool& check_jtrk = ( this->*m_patternStrategyFuncs[m_checkPatternStrategy] )( jtrk, FitVertex );
     
-    const uint32_t pattern = trk->hitPattern();
+    return ( check_itrk && check_jtrk );
+    
+#if 0
+    const double rad  = sqrt(FitVertex.x()*FitVertex.x() + FitVertex.y()*FitVertex.y()); 
+    const double absz = fabs( FitVertex.z() );
+    
+    const uint32_t pattern_itrk = itrk->hitPattern();
+    const uint32_t pattern_jtrk = jtrk->hitPattern();
     
 	
     if( m_geoModel == VKalVrtAthena::GeoModel::Run2 ) {
@@ -1332,112 +1472,155 @@ namespace VKalVrtAthena {
       //////////////////////////////////////////////////////////////////////////////////
       if( vertex_pattern == insideBeamPipe ) {
 	
-	if( ! (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
 	
 	
       } else if( vertex_pattern == insidePixelBarrel0 ) {
 	
-	if( ! (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel0 ) {
 	
 	// require nothing for PixelBarrel0
-	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel0_and_insidePixelBarrel1 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel1 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
 	// require nothing for PixelBarrel1
-	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel1_and_insidePixelBarrel2 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel2 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
 	// require nothing for PixelBarrel2
-	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
       }
       
 
       else if( vertex_pattern == outsidePixelBarrel2_and_insidePixelBarrel3 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
       }
 	
       else if( vertex_pattern == aroundPixelBarrel3 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
 	// require nothing for PixelBarrel3
-	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel3_and_insideSctBarrel0 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel0 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
 	// require nothing for SctBarrel0
-	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsideSctBarrel0_and_insideSctBarrel1 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel1 ) {
-	if(   (pattern & (1<<Trk::pixelBarrel0)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
 	// require nothing for SctBarrel1
-	if( ! (pattern & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel2)) ) return false;
       }
       //////////////////////////////////////////////////////////////////////////////////
       
@@ -1516,91 +1699,122 @@ namespace VKalVrtAthena {
       //////////////////////////////////////////////////////////////////////////////////
       if( vertex_pattern == insideBeamPipe ) {
 	
-	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
 	
       }
       
       
       else if( vertex_pattern == insidePixelBarrel1 ) {
 	
-	if( ! (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel1 ) {
 	
 	// require nothing for PixelBarrel1
-	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel1_and_insidePixelBarrel2 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if( ! (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundPixelBarrel2 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
 	// require nothing for PixelBarrel2
-	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
       }
       
 
       else if( vertex_pattern == outsidePixelBarrel2_and_insidePixelBarrel3 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if( ! (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
       }
 	
       else if( vertex_pattern == aroundPixelBarrel3 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
 	// require nothing for PixelBarrel3
-	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == outsidePixelBarrel3_and_insideSctBarrel0 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if( ! (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel0 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
 	// require nothing for SctBarrel0
-	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == outsideSctBarrel0_and_insideSctBarrel1 ) {
 	
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
-	if( ! (pattern & (1<<Trk::sctBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel1)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel1)) ) return false;
       }
       
       
       else if( vertex_pattern == aroundSctBarrel1 ) {
-	if(   (pattern & (1<<Trk::pixelBarrel1)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel2)) ) return false;
-	if(   (pattern & (1<<Trk::pixelBarrel3)) ) return false;
-	if(   (pattern & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel1)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel2)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::pixelBarrel3)) ) return false;
+	if(   (pattern_itrk & (1<<Trk::sctBarrel0)) ) return false;
+	if(   (pattern_jtrk & (1<<Trk::sctBarrel0)) ) return false;
 	// require nothing for SctBarrel1
-	if( ! (pattern & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern_itrk & (1<<Trk::sctBarrel2)) ) return false;
+	if( ! (pattern_jtrk & (1<<Trk::sctBarrel2)) ) return false;
       }
       //////////////////////////////////////////////////////////////////////////////////
       
@@ -1609,9 +1823,9 @@ namespace VKalVrtAthena {
     }
     
     return true;
+#endif
   }
   
-
 } // end of namespace VKalVrtAthena
 
 
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx
index 1f67ae16e293..2bb91bd1a192 100644
--- a/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx
@@ -151,6 +151,7 @@ namespace VKalVrtAthena {
 
         // fake rejection cuts with track hit pattern consistencies
         if( m_removeFakeVrt && !(this->passedFakeReject( FitVertex, (*itrk), (*jtrk) )) ) continue;
+        //if( m_removeFakeVrt && !(this->passedFakeRejectByExtrapolation( FitVertex, *itrk, *jtrk )) ) continue;
 
 
         if( m_FillNtuple ) {
@@ -819,7 +820,7 @@ namespace VKalVrtAthena {
           
           if( &workVertex == &vertexToAttach ) continue;
           if( workVertex.SelTrk.size() >= vertexToAttach.SelTrk.size() ) continue;
-          if( !checkTrackHitPatternToVertex( trk, vertexToAttach.vertex ) ) continue;
+          if( ! ( this->*m_patternStrategyFuncs[m_checkPatternStrategy] )( trk, vertexToAttach.vertex ) ) continue;
           
           // Get the closest approach
           std::vector<double> impactParameters;
@@ -931,8 +932,6 @@ namespace VKalVrtAthena {
           if( result != associableTracks->end() ) continue;
         }
         
-        if( !checkTrackHitPatternToVertex( trk, vertexPos ) ) continue;
-        
         // Get the closest approach
         std::vector<double> impactParameters;
         std::vector<double> impactParErrors;
@@ -943,6 +942,8 @@ namespace VKalVrtAthena {
         
         if( hypot( impactParameters.at(k_d0), impactParameters.at(k_z0) ) > 1.0 ) continue;
         
+        if( ! ( this->*m_patternStrategyFuncs[m_checkPatternStrategy] )( trk, vertexPos ) ) continue;
+        
         ATH_MSG_DEBUG( " >> associateNonSeletedTracks: trk " << trk
                        << ": d0 to vtx = " << impactParameters.at(k_d0)
                        << ", z0 to vtx = " << impactParameters.at(k_z0)
diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/VrtSecInclusive.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/VrtSecInclusive.cxx
index 9936a4825c08..f7febf4c869d 100644
--- a/Reconstruction/VKalVrt/VrtSecInclusive/src/VrtSecInclusive.cxx
+++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/VrtSecInclusive.cxx
@@ -130,6 +130,13 @@ namespace VKalVrtAthena {
     m_trackToVertexTool            ( "Reco::TrackToVertex" ),
     m_trackToVertexIPEstimatorTool ( "Trk::TrackToVertexIPEstimator/TrackToVertexIPEstimator" ),
     m_vertexMapper                 ( "" ),
+    m_extrapolationEngine          ( "" ),
+    
+    // Services
+    m_pixelCondSummarySvc          ( "PixelConditionsSummarySvc", "VrtSecInclusive" ),
+    m_sctCondSummarySvc            ( "SCT_ConditionsSummarySvc", "VrtSecInclusive" ),
+    
+    m_checkPatternStrategy( "Classical" ),
     
     // Histograms for stats
     // (Hide: from C++11 "nullptr" is recommended for NULL)
@@ -146,8 +153,11 @@ namespace VKalVrtAthena {
     
     m_importedTrkTruthColl     ( nullptr ),
     m_importedFullTruthColl    ( nullptr )
-    
+
   {
+    
+    m_patternStrategyFuncs["Classical"]     = &VrtSecInclusive::checkTrackHitPatternToVertex;
+    m_patternStrategyFuncs["Extrapolation"] = &VrtSecInclusive::checkTrackHitPatternToVertexByExtrapolation;
 
     this->declareProperties();
     
@@ -224,6 +234,13 @@ namespace VKalVrtAthena {
       ATH_MSG_INFO("initialize: Retrieved Trk::TrackToVertexIPEstimator Tool" << m_trackToVertexIPEstimatorTool);
     }
     
+    
+    if( detStore()->retrieve(m_atlasId, "AtlasID").isFailure() ) return StatusCode::SUCCESS;
+    if( detStore()->retrieve(m_pixelId, "PixelID").isFailure() ) return StatusCode::SUCCESS;
+    if( detStore()->retrieve(m_sctId,   "SCT_ID") .isFailure() ) return StatusCode::SUCCESS;
+    
+    ATH_CHECK( m_extrapolationEngine.retrieve() );
+    
     // extract VertexMapper
     if( m_doMapToLocal ) {
       ATH_CHECK( m_vertexMapper.retrieve() );
-- 
GitLab