diff --git a/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h b/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
index 21fb2f462383f848c26d6f5be329fbb7158dcedd..4784ffabce82c56c02a4eb27a532068688d3a828 100644
--- a/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
+++ b/Control/AthenaBaseComps/AthenaBaseComps/AthReentrantAlgorithm.h
@@ -136,6 +136,14 @@ class AthReentrantAlgorithm
    */
   virtual const DataObjIDColl& extraOutputDeps() const override;
 
+  virtual bool filterPassed(const EventContext& ctx) const {
+    return execState( ctx ).filterPassed();
+  }
+
+  virtual void setFilterPassed( bool state, const EventContext& ctx ) const {
+    execState( ctx ).setFilterPassed( state );
+  }
+
 
  private: 
 
diff --git a/MuonSpectrometer/MuonCalib/NSWCalib/NSWCalibTools/src/NSWCalibTool.cxx b/MuonSpectrometer/MuonCalib/NSWCalib/NSWCalibTools/src/NSWCalibTool.cxx
index e062ad50ba94e0c86e717aa0fca9488b1e07ffd2..06069815b7a3fec0e39574c4c5d4ec516cae11bd 100644
--- a/MuonSpectrometer/MuonCalib/NSWCalib/NSWCalibTools/src/NSWCalibTool.cxx
+++ b/MuonSpectrometer/MuonCalib/NSWCalib/NSWCalibTools/src/NSWCalibTool.cxx
@@ -140,12 +140,9 @@ StatusCode Muon::NSWCalibTool::calibrateStrip(const Muon::MM_RawData* mmRawData,
 {
   Identifier rdoId = mmRawData->identify();
 
-  // @TODO: for the shifter: this code will be used as soon as the NSW is built in the MuonDetectorCondAlg
-  // for now, we will need to use the nominal manager from the detectorStore to run
-  // SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey};
-  // const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
-  const MuonGM::MuonDetectorManager* muDetMgr=nullptr;
-  ATH_CHECK(detStore()->retrieve(muDetMgr));
+  // MuonDetectorManager from the conditions store
+  SG::ReadCondHandle<MuonGM::MuonDetectorManager> muDetMgrHandle{m_muDetMgrKey};
+  const MuonGM::MuonDetectorManager* muDetMgr = muDetMgrHandle.cptr();
 
   //get globalPos
   Amg::Vector3D globalPos;
diff --git a/MuonSpectrometer/MuonCnv/MuonSTGC_CnvTools/src/sTgcRdoToPrepDataToolCore.cxx b/MuonSpectrometer/MuonCnv/MuonSTGC_CnvTools/src/sTgcRdoToPrepDataToolCore.cxx
index 25924a048ded723f70e793f9a108882ddb3d4752..5166bfd20f33d8f0fd0720ebdfc0225a0d6b0e04 100644
--- a/MuonSpectrometer/MuonCnv/MuonSTGC_CnvTools/src/sTgcRdoToPrepDataToolCore.cxx
+++ b/MuonSpectrometer/MuonCnv/MuonSTGC_CnvTools/src/sTgcRdoToPrepDataToolCore.cxx
@@ -83,6 +83,15 @@ StatusCode Muon::sTgcRdoToPrepDataToolCore::processCollection(const STGC_RawData
   std::vector<sTgcPrepData> sTgcPadPrds;
   // convert the RDO collection to a PRD collection
   STGC_RawDataCollection::const_iterator it = rdoColl->begin();
+  
+  // MuonDetectorManager from the conditions store
+  SG::ReadCondHandle<MuonGM::MuonDetectorManager> detMgrHandle{m_muDetMgrKey};
+  const MuonGM::MuonDetectorManager* muonDetMgr = detMgrHandle.cptr(); 
+  if(!muonDetMgr){
+    ATH_MSG_ERROR("Null pointer to the read MuonDetectorManager conditions object");
+    return StatusCode::FAILURE;
+  }
+  
   for ( ; it != rdoColl->end() ; ++it ) {
 
     ATH_MSG_DEBUG("Adding a new sTgc PrepRawData");
@@ -95,14 +104,9 @@ StatusCode Muon::sTgcRdoToPrepDataToolCore::processCollection(const STGC_RawData
     }
     std::vector<Identifier> rdoList;
     rdoList.push_back(rdoId);
-
-    // TODO: this needs to be replaced by SG::ReadCondHandle<MuonGM::MuonDetectorManager>
-    // will do it in a follow-up MR, since for now, we need to get the Run2 detectors running, so skip sTGCs for now
-    const MuonGM::MuonDetectorManager* muDetMgrNominal=nullptr;
-    ATH_CHECK(detStore()->retrieve(muDetMgrNominal));
     
     // get the local and global positions
-    const MuonGM::sTgcReadoutElement* detEl = muDetMgrNominal->getsTgcReadoutElement(rdoId);
+    const MuonGM::sTgcReadoutElement* detEl = muonDetMgr->getsTgcReadoutElement(rdoId);
     Amg::Vector2D localPos;
 
     bool getLocalPos = detEl->stripPosition(rdoId,localPos);
diff --git a/MuonSpectrometer/MuonIdHelpersAlgs/MuonIdHelpersAlgs/TestMuonIdHelpers.h b/MuonSpectrometer/MuonIdHelpersAlgs/MuonIdHelpersAlgs/TestMuonIdHelpers.h
index f8e34a66ce252f7a5008dd2bd6b8f3e6c241277c..704ebace7eb1cfa2deafc13abd0b645401e6332f 100644
--- a/MuonSpectrometer/MuonIdHelpersAlgs/MuonIdHelpersAlgs/TestMuonIdHelpers.h
+++ b/MuonSpectrometer/MuonIdHelpersAlgs/MuonIdHelpersAlgs/TestMuonIdHelpers.h
@@ -5,16 +5,18 @@
 #ifndef TestMuonIdHelpers_H
 #define TestMuonIdHelpers_H
 
-#include <vector>
-
 #include "AthenaBaseComps/AthAlgorithm.h"
 #include "GaudiKernel/ServiceHandle.h"
-#include "MuonIdHelpers/IMuonIdHelperSvc.h"
+#include "StoreGate/ReadHandleKey.h"
 
-class StoreGateSvc;
-class ActiveStoreSvc;
+#include "MuonIdHelpers/IMuonIdHelperSvc.h"
+#include "MuonDigitContainer/MdtDigitContainer.h"
+#include "MuonDigitContainer/RpcDigitContainer.h"
+#include "MuonDigitContainer/CscDigitContainer.h"
+#include "MuonDigitContainer/TgcDigitContainer.h"
 
-/////////////////////////////////////////////////////////////////////////////
+#include <string>
+#include <vector>
 
 class TestMuonIdHelpers : public AthAlgorithm {
 
@@ -44,9 +46,13 @@ private:
   BooleanProperty m_testRPC;
   BooleanProperty m_testTGC;
 
-  ServiceHandle<ActiveStoreSvc> m_activeStore;
   ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};
 
+  SG::ReadHandleKey<MdtDigitContainer> m_mdtDigitContKey{this,"MdtDigits","MDT_DIGITS","ReadHandleKey for Input MdtDigitContainer"};
+  SG::ReadHandleKey<RpcDigitContainer> m_rpcDigitContKey{this,"RpcDigits","RPC_DIGITS","ReadHandleKey for Input RpcDigitContainer"};
+  SG::ReadHandleKey<CscDigitContainer> m_cscDigitContKey{this,"CscDigits","CSC_DIGITS","ReadHandleKey for Input CscDigitContainer"};
+  SG::ReadHandleKey<TgcDigitContainer> m_tgcDigitContKey{this,"TgcDigits","TGC_DIGITS","ReadHandleKey for Input TgcDigitContainer"};
+
   mutable std::atomic<long long> m_deltaUser{0};
   mutable std::atomic<long long> m_deltaKernel{0};
   mutable std::atomic<long long> m_deltaElapsed{0};
diff --git a/MuonSpectrometer/MuonIdHelpersAlgs/src/TestMuonIdHelpers.cxx b/MuonSpectrometer/MuonIdHelpersAlgs/src/TestMuonIdHelpers.cxx
index 6cb950c02a130777da28783c103f11a567127d3c..d937dbe05b38ef13f2092ef76a89586ba35ebb4e 100644
--- a/MuonSpectrometer/MuonIdHelpersAlgs/src/TestMuonIdHelpers.cxx
+++ b/MuonSpectrometer/MuonIdHelpersAlgs/src/TestMuonIdHelpers.cxx
@@ -4,33 +4,11 @@
 
 #include "MuonIdHelpersAlgs/TestMuonIdHelpers.h"
 
-#include "MuonDigitContainer/MdtDigitContainer.h"
-#include "MuonDigitContainer/MdtDigitCollection.h"
-#include "MuonDigitContainer/MdtDigit.h"
-
-#include "MuonDigitContainer/CscDigitContainer.h"
-#include "MuonDigitContainer/CscDigitCollection.h"
-#include "MuonDigitContainer/CscDigit.h"
-
-#include "MuonDigitContainer/RpcDigitContainer.h"
-#include "MuonDigitContainer/RpcDigitCollection.h"
-#include "MuonDigitContainer/RpcDigit.h"
-
-#include "MuonDigitContainer/TgcDigitContainer.h"
-#include "MuonDigitContainer/TgcDigitCollection.h"
-#include "MuonDigitContainer/TgcDigit.h"
-
-#include "MuonReadoutGeometry/MuonDetectorManager.h"
-
 #include <algorithm>
 #include <cmath>
 
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
 TestMuonIdHelpers::TestMuonIdHelpers(const std::string& name, ISvcLocator* pSvcLocator) :
-  AthAlgorithm(name, pSvcLocator),
-  m_activeStore("ActiveStoreSvc", name) {
+  AthAlgorithm(name, pSvcLocator) {
 
   m_testMDT = true;
   m_testCSC = true;
@@ -51,10 +29,13 @@ StatusCode TestMuonIdHelpers::initialize(){
 
   ATH_MSG_DEBUG(" in initialize()");
 
-  ATH_CHECK(m_activeStore.retrieve());
-
   ATH_CHECK(m_idHelperSvc.retrieve());
 
+  ATH_CHECK(m_mdtDigitContKey.initialize());
+  ATH_CHECK(m_rpcDigitContKey.initialize());
+  ATH_CHECK(m_cscDigitContKey.initialize());
+  ATH_CHECK(m_tgcDigitContKey.initialize());
+
   return StatusCode::SUCCESS;
 
 }
@@ -104,10 +85,12 @@ StatusCode TestMuonIdHelpers::testMdtIdHelper() const {
   // retrieve data from StoreGate
   typedef MdtDigitContainer::const_iterator collection_iterator;
   typedef MdtDigitCollection::const_iterator digit_iterator;
-  
-  std::string key = "MDT_DIGITS";
-  const DataHandle <MdtDigitContainer> container;
-  ATH_CHECK( (*m_activeStore)->retrieve(container,key) );
+
+  SG::ReadHandle<MdtDigitContainer> container(m_mdtDigitContKey);
+  if (!container.isValid()) {
+    ATH_MSG_ERROR("Could not find MdtDigitContainer called " << container.name() << " in store " << container.store());
+    return StatusCode::FAILURE;
+  }
   collection_iterator it1_coll= container->begin(); 
   collection_iterator it2_coll= container->end(); 
 
@@ -121,7 +104,8 @@ StatusCode TestMuonIdHelpers::testMdtIdHelper() const {
     ++nc1; 
     Identifier moduleId = mdtCollection->identify();
     if (!m_idHelperSvc->mdtIdHelper().validElement(moduleId)) {
-      ATH_MSG_ERROR( "Invalid MDT module identifier " << m_idHelperSvc->mdtIdHelper().show_to_string(moduleId)  );
+      ATH_MSG_ERROR( "Invalid MDT module identifier " << m_idHelperSvc->mdtIdHelper().show_to_string(moduleId));
+      return StatusCode::FAILURE;
     }
     digit_iterator it1_digit = mdtCollection->begin();
     digit_iterator it2_digit = mdtCollection->end();
@@ -138,9 +122,11 @@ StatusCode TestMuonIdHelpers::testMdtIdHelper() const {
   }
   ATH_MSG_DEBUG("  Number of MDT Collections  Accessed " << nc1  );
 
-  if(error) ATH_MSG_ERROR( "Check of MDT ids FAILED "  );
-  else      ATH_MSG_INFO( "Check of MDT ids OK "  );
-  
+  if(error) {
+    ATH_MSG_ERROR( "Check of MDT ids FAILED "  );
+    return StatusCode::FAILURE;
+  }
+  else ATH_MSG_INFO( "Check of MDT ids OK "  );
  return StatusCode::SUCCESS;
 }
 
@@ -158,10 +144,12 @@ StatusCode TestMuonIdHelpers::testCscIdHelper() const {
   // retrieve data from StoreGate
   typedef CscDigitContainer::const_iterator collection_iterator;
   typedef CscDigitCollection::const_iterator digit_iterator;
-  
-  std::string key = "CSC_DIGITS";
-  const DataHandle <CscDigitContainer> container;
-  ATH_CHECK( (*m_activeStore)->retrieve(container,key) );
+
+  SG::ReadHandle<CscDigitContainer> container(m_cscDigitContKey);
+  if (!container.isValid()) {
+    ATH_MSG_ERROR("Could not find CscDigitContainer called " << container.name() << " in store " << container.store());
+    return StatusCode::FAILURE;
+  }
   collection_iterator it1_coll= container->begin(); 
   collection_iterator it2_coll= container->end(); 
 
@@ -175,7 +163,8 @@ StatusCode TestMuonIdHelpers::testCscIdHelper() const {
     ++nc1; 
     Identifier moduleId = cscCollection->identify();
     if (!m_idHelperSvc->cscIdHelper().validElement(moduleId)) {
-      ATH_MSG_ERROR( "Invalid CSC module identifier " << m_idHelperSvc->cscIdHelper().show_to_string(moduleId)  );
+      ATH_MSG_ERROR( "Invalid CSC module identifier " << m_idHelperSvc->cscIdHelper().show_to_string(moduleId));
+      return StatusCode::FAILURE;
     }
     digit_iterator it1_digit = cscCollection->begin();
     digit_iterator it2_digit = cscCollection->end();
@@ -192,9 +181,10 @@ StatusCode TestMuonIdHelpers::testCscIdHelper() const {
   }
   ATH_MSG_DEBUG("Number of CSC Collections  Accessed " << nc1  );
 
-  if(error) ATH_MSG_ERROR( "Check of CSC ids FAILED "  );
-  else      ATH_MSG_INFO( "Check of CSC ids OK "  );
-  
+  if(error) {
+    ATH_MSG_ERROR( "Check of CSC ids FAILED "  );
+    return StatusCode::FAILURE;
+  } else ATH_MSG_INFO( "Check of CSC ids OK "  );
   return StatusCode::SUCCESS;
 }
 
@@ -211,10 +201,12 @@ StatusCode TestMuonIdHelpers::testRpcIdHelper() const {
   // retrieve data from StoreGate
   typedef RpcDigitContainer::const_iterator collection_iterator;
   typedef RpcDigitCollection::const_iterator digit_iterator;
-  
-  std::string key = "RPC_DIGITS";
-  const DataHandle <RpcDigitContainer> container;
-  ATH_CHECK( (*m_activeStore)->retrieve(container,key) );
+
+  SG::ReadHandle<RpcDigitContainer> container(m_rpcDigitContKey);
+  if (!container.isValid()) {
+    ATH_MSG_ERROR("Could not find RpcDigitContainer called " << container.name() << " in store " << container.store());
+    return StatusCode::FAILURE;
+  }
   collection_iterator it1_coll= container->begin(); 
   collection_iterator it2_coll= container->end(); 
 
@@ -228,7 +220,8 @@ StatusCode TestMuonIdHelpers::testRpcIdHelper() const {
     ++nc1; 
     Identifier moduleId = rpcCollection->identify();
     if (!m_idHelperSvc->rpcIdHelper().validElement(moduleId)) {
-      ATH_MSG_ERROR( "Invalid RPC module identifier " << m_idHelperSvc->rpcIdHelper().show_to_string(moduleId)  );
+      ATH_MSG_ERROR( "Invalid RPC module identifier " << m_idHelperSvc->rpcIdHelper().show_to_string(moduleId));
+      return StatusCode::FAILURE;
     }
     digit_iterator it1_digit = rpcCollection->begin();
     digit_iterator it2_digit = rpcCollection->end();
@@ -245,8 +238,11 @@ StatusCode TestMuonIdHelpers::testRpcIdHelper() const {
   }
   ATH_MSG_DEBUG("  Number of RPC Collections  Accessed " << nc1  );
 
-  if(error) ATH_MSG_ERROR( "Check of RPC ids FAILED "  );
-  else      ATH_MSG_INFO( "Check of RPC ids OK "  );
+  if(error) {
+    ATH_MSG_ERROR("Check of RPC ids FAILED");
+    return StatusCode::FAILURE;
+  }
+  else ATH_MSG_INFO( "Check of RPC ids OK "  );
   
   return StatusCode::SUCCESS;
 }
@@ -264,10 +260,12 @@ StatusCode TestMuonIdHelpers::testTgcIdHelper() const {
   // retrieve data from StoreGate
   typedef TgcDigitContainer::const_iterator collection_iterator;
   typedef TgcDigitCollection::const_iterator digit_iterator;
-  
-  std::string key = "TGC_DIGITS";
-  const DataHandle <TgcDigitContainer> container;
-  ATH_CHECK( (*m_activeStore)->retrieve(container,key) );
+
+  SG::ReadHandle<TgcDigitContainer> container(m_tgcDigitContKey);
+  if (!container.isValid()) {
+    ATH_MSG_ERROR("Could not find TgcDigitContainer called " << container.name() << " in store " << container.store());
+    return StatusCode::FAILURE;
+  }
   collection_iterator it1_coll= container->begin(); 
   collection_iterator it2_coll= container->end(); 
 
@@ -281,7 +279,8 @@ StatusCode TestMuonIdHelpers::testTgcIdHelper() const {
     ++nc1; 
     Identifier moduleId = tgcCollection->identify();
     if (!m_idHelperSvc->tgcIdHelper().validElement(moduleId)) {
-      ATH_MSG_ERROR( "Invalid TGC module identifier " << m_idHelperSvc->tgcIdHelper().show_to_string(moduleId)  );
+      ATH_MSG_ERROR( "Invalid TGC module identifier " << m_idHelperSvc->tgcIdHelper().show_to_string(moduleId));
+      return StatusCode::FAILURE;
     }
     digit_iterator it1_digit = tgcCollection->begin();
     digit_iterator it2_digit = tgcCollection->end();
@@ -298,8 +297,10 @@ StatusCode TestMuonIdHelpers::testTgcIdHelper() const {
   }
   ATH_MSG_DEBUG("Number of TGC Collections  Accessed " << nc1  );
 
-  if(error) ATH_MSG_ERROR( "Check of TGC ids FAILED "  );
-  else      ATH_MSG_INFO( "Check of TGC ids OK "  );
+  if(error) {
+    ATH_MSG_ERROR( "Check of TGC ids FAILED ");
+    return StatusCode::FAILURE;
+  } else ATH_MSG_INFO( "Check of TGC ids OK ");
   
   return StatusCode::SUCCESS;
 }
diff --git a/PhysicsAnalysis/CommonTools/ExpressionEvaluation/ExpressionEvaluation/StackElement.icc b/PhysicsAnalysis/CommonTools/ExpressionEvaluation/ExpressionEvaluation/StackElement.icc
index 309b6b000b72c8373cfb6300906fe45026cda77a..9f728b7e38a8f67361a789e43829f2a88216c2ae 100644
--- a/PhysicsAnalysis/CommonTools/ExpressionEvaluation/ExpressionEvaluation/StackElement.icc
+++ b/PhysicsAnalysis/CommonTools/ExpressionEvaluation/ExpressionEvaluation/StackElement.icc
@@ -37,12 +37,12 @@ namespace ExpressionParsing {
         m_variableType(static_cast<IProxyLoader::VariableType>(a.m_variableType)),
         m_determinedVariableType(a.m_determinedVariableType ? true : false)
    {
-      if (a.m_moved) throw std::logic_error("Content already moved"); \
+      if (a.m_moved) throw std::logic_error("Content already moved");
    }
 
    inline StackElement &StackElement::operator=(StackElement &&a) {
       if (&a != this) {
-         if (a.m_moved) throw std::logic_error("Content already moved"); \
+         if (a.m_moved) throw std::logic_error("Content already moved");
          m_type                   = a.m_type;
          m_intVal                 = a.m_intVal;
          m_doubleVal              = a.m_doubleVal;
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/CMakeLists.txt b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..74c6928b2aa9f43cfaa6dc09848413b590ef39e8
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/CMakeLists.txt
@@ -0,0 +1,40 @@
+################################################################################
+# Package: NewVrtSecInclusiveTool
+################################################################################
+
+# Declare the package name:
+atlas_subdir( NewVrtSecInclusiveTool )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaBaseComps
+                          Event/xAOD/xAODTracking
+                          GaudiKernel
+                          PRIVATE
+                          Tools/PathResolver
+                          DetectorDescription/GeoPrimitives
+                          Tracking/TrkExtrapolation/TrkExInterfaces
+			  Reconstruction/MVAUtils
+                          Tracking/TrkEvent/VxSecVertex
+                          Tracking/TrkVertexFitter/TrkVKalVrtFitter
+ 			  InnerDetector/InDetConditions/InDetBeamSpotService)
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( Eigen )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread TMVA )
+
+# Component(s) in the package:
+atlas_add_component( NewVrtSecInclusiveTool 
+                     src/*.cxx  src/components/*.cxx
+                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+                LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${EIGEN_LIBRARIES} AthenaBaseComps xAODTracking PathResolver GaudiKernel 
+		Particle TrkVKalVrtFitterLib GeoPrimitives MVAUtils AnalysisUtilsLib TrkParticleBase 
+		TrkTrackSummary TrkExInterfaces VxSecVertex )
+ 
+# Install files from the package:
+atlas_install_headers( NewVrtSecInclusiveTool )
+atlas_install_python_modules( python/*.py )
+#atlas_install_joboptions( share/*.txt )
+#atlas_install_data( share/*.root )
+
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/ATLAS_CHECK_THREAD_SAFETY b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/ATLAS_CHECK_THREAD_SAFETY
new file mode 100644
index 0000000000000000000000000000000000000000..0c630dd36b6cb9c47f9ca3a056eb224244c94ba0
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/ATLAS_CHECK_THREAD_SAFETY
@@ -0,0 +1 @@
+Reconstruction/VKalVrt/NewVrtSecInclusiveTool
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/IVrtInclusive.h b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/IVrtInclusive.h
new file mode 100755
index 0000000000000000000000000000000000000000..3ab765839cbe0654b055558d41923b2854aa5297
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/IVrtInclusive.h
@@ -0,0 +1,62 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+//
+// IVrtInclusive.h - Description
+//
+/*
+   Interface for inclusive secondary vertex reconstruction
+   It returns a pointer to Trk::VxSecVertexInfo object which contains
+   vector of pointers to xAOD::Vertex's of found secondary verteces.
+   In case of failure pointer to Trk::VxSecVertexInfo is 0.
+   
+
+   Tool creates a derivative object VxSecVKalVertexInfo which contains also additional variables
+   see  Tracking/TrkEvent/VxSecVertex/VxSecVertex/VxSecVKalVertexInfo.h
+   
+    Author: Vadim Kostyukhin
+    e-mail: vadim.kostyukhin@cern.ch
+
+-----------------------------------------------------------------------------*/
+
+
+
+#ifndef _Rec_IVrtSecInclusive_H
+#define _Rec_IVrtSecInclusive_H
+// Normal STL and physical vectors
+#include <vector>
+// Gaudi includes
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "xAODTracking/TrackParticleContainer.h"
+#include "xAODTracking/VertexContainer.h"
+#include "VxSecVertex/VxSecVertexInfo.h"
+
+ 
+//------------------------------------------------------------------------
+namespace Rec {
+
+//------------------------------------------------------------------------
+  static const InterfaceID IID_IVrtInclusive("IVrtInclusive", 1, 0);
+
+  class IVrtInclusive : virtual public IAlgTool {
+    public:
+      static const InterfaceID& interfaceID() { return IID_IVrtInclusive;}
+//---------------------------------------------------------------------------
+
+  /** @class IVrtInclusive
+
+    Interface class for inclusive vertex reconstruction.
+    All secondary vertices produced in a phase space around Primary Vertex(PV) and resulted in secondary tracks 
+    provided by inputTracks collection are returned in Trk::VxSecVertexInfo.
+    Interface assumes that necessary TrackParticles can be pre-selected by user before calling the actual tool implementation
+    with default track quality cuts.
+    
+  */
+      virtual std::unique_ptr<Trk::VxSecVertexInfo> findAllVertices( const std::vector<const xAOD::TrackParticle*> & inputTracks,
+                                                     const xAOD::Vertex & PV) const =0;
+
+  };
+
+}  //end namespace
+
+#endif
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h
new file mode 100755
index 0000000000000000000000000000000000000000..2749aa5c1aea70ac5329211bbd2e6b5917bb9c22
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h
@@ -0,0 +1,396 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+//
+// NewVrtSecInclusiveTool.h - Description
+//
+/*
+   Tool for inclusive secondary vertex reconstruction
+   It returns a pointer to Trk::VxSecVertexInfo object which contains
+   vector of pointers to xAOD::Vertex's of found secondary verteces.
+   In case of failure pointer to Trk::VxSecVertexInfo is 0.
+   
+
+   Tool creates a derivative object VxSecVKalVertexInfo which contains also additional variables
+   see  Tracking/TrkEvent/VxSecVertex/VxSecVertex/VxSecVKalVertexInfo.h
+   
+
+    Author: Vadim Kostyukhin
+    e-mail: vadim.kostyukhin@cern.ch
+
+-----------------------------------------------------------------------------*/
+
+
+
+#ifndef _VKalVrt_NewVrtSecInclusiveTool_H
+#define _VKalVrt_NewVrtSecInclusiveTool_H
+// Normal STL and physical vectors
+#include <vector>
+// Gaudi includes
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "boost/graph/adjacency_list.hpp"
+//
+#include "xAODTruth/TruthEventContainer.h"
+#include "TrkExInterfaces/IExtrapolator.h"
+//
+#include "VxSecVertex/VxSecVertexInfo.h"
+#include "NewVrtSecInclusiveTool/IVrtInclusive.h"
+
+class TH1D;
+class TH2D;
+class TH1F;
+class TProfile;
+class TTree;
+class IBeamCondSvc;
+
+namespace Trk{
+  class TrkVKalVrtFitter;
+  class IVertexFitter;
+  class IVKalState;
+}
+ 
+namespace MVAUtils { class BDT; }
+
+typedef std::vector<double> dvect;
+
+ 
+//------------------------------------------------------------------------
+namespace Rec {
+
+  struct workVectorArrxAOD{
+        std::vector<const xAOD::TrackParticle*> listSelTracks;  // Selected tracks after quality cuts
+        std::vector<const xAOD::TrackParticle*> tmpListTracks;
+        std::vector<const xAOD::TrackParticle*> inpTrk;         // All tracks provided to tool
+        double beamX=0.;
+        double beamY=0.;
+        double beamZ=0.;
+        double tanBeamTiltX=0.;
+        double tanBeamTiltY=0.;
+  };
+
+  class NewVrtSecInclusiveTool : public AthAlgTool, virtual public IVrtInclusive
+  {
+
+
+  public:
+       /* Constructor */
+      NewVrtSecInclusiveTool(const std::string& type, const std::string& name, const IInterface* parent);
+       /* Destructor */
+      virtual ~NewVrtSecInclusiveTool();
+
+
+      StatusCode initialize();
+      StatusCode finalize();
+
+
+
+      std::unique_ptr<Trk::VxSecVertexInfo> findAllVertices(const std::vector<const xAOD::TrackParticle*> & inputTracks,
+                                                                                     const xAOD::Vertex & primaryVertex) const final;
+//------------------------------------------------------------------------------------------------------------------
+// Private data and functions
+//
+
+    private:
+
+      double m_w_1{};
+      TTree* m_tuple{};
+      TH1D* m_hb_massPiPi{};
+      TH1D* m_hb_massPiPi1{};
+      TH1D* m_hb_massPPi{};
+      TH1D* m_hb_massEE{};
+      TH1D* m_hb_nvrt2{};
+      TH1D* m_hb_ratio{};
+      TH1D* m_hb_totmass{};
+      TH1D* m_hb_impact{};
+      TH1D* m_hb_impactR{};
+      TH2D* m_hb_impactRZ{};
+      TH1D* m_hb_pileupRat{};
+      TH1D* m_hb_trkD0{};
+      TH1D* m_hb_trkZ{};
+      TH1F* m_hb_ntrksel{};
+      TH1F* m_hb_ntrkInput{};
+      TH1F* m_hb_trkSelect{};
+      TH1D* m_hb_impactZ{};
+      TH1D* m_hb_r2d{};
+      TH1D* m_hb_signif3D{};
+      TH1D* m_hb_impV0{};
+      TH1D* m_hb_sig3DTot{};
+      TH1F* m_hb_goodvrtN{};
+      TH1F* m_hb_goodvrt1N{};
+      TH1D* m_hb_distVV{};
+      TH1D* m_hb_diffPS{};
+      TH1D* m_hb_sig3D1tr{};
+      TH1D* m_hb_sig3D2tr{};
+      TH1D* m_hb_sig3DNtr{};
+      TH1F* m_hb_rawVrtN{};
+      TH1F* m_hb_cosSVMom{};
+      TH1F* m_hb_etaSV{};
+      TH1F* m_hb_fakeSVBDT{};
+//--
+
+      long int m_cutSctHits{};
+      long int m_cutPixelHits{};
+      long int m_cutSiHits{};
+      long int m_cutBLayHits{};
+      long int m_cutSharedHits{};
+      double m_cutPt{};
+      double m_cutZVrt{};
+      double m_cutA0{};
+      double m_cutChi2{};
+      double m_sel2VrtProbCut{};
+      double m_globVrtProbCut{};
+      double m_maxSVRadiusCut{};
+      double m_selVrtSigCut{};
+      double m_trkSigCut{};
+      float m_a0TrkErrorCut{};
+      float m_zTrkErrorCut{};
+      float m_VrtMassLimit{};
+      float m_Vrt2TrMassLimit{};
+      float m_Vrt2TrPtLimit{};
+      float m_antiPileupSigRCut{};
+      float m_dRdZRatioCut{};
+      float m_v2tIniBDTCut{};
+      float m_v2tFinBDTCut{};
+      float m_vertexMergeCut{};
+      float m_trackDetachCut{};
+      float m_beampipeR{};
+      float m_removeTrkMatSignif{};
+
+      bool m_fillHist{};
+      bool m_useVertexCleaning{};
+      bool m_multiWithOneTrkVrt{};
+      std::string m_calibFileName;
+
+      std::unique_ptr<MVAUtils::BDT> m_SV2T_BDT;
+
+      ServiceHandle< IBeamCondSvc > m_beamService; 
+      //ToolHandle<Trk::IVertexFitter>  m_fitterSvc;
+      ToolHandle<Trk::IExtrapolator>  m_extrapolator{this,"ExtrapolatorName","Trk::Extrapolator/Extrapolator"};
+      ToolHandle<Trk::TrkVKalVrtFitter>  m_fitSvc;
+      //Trk::TrkVKalVrtFitter*   m_fitSvc{};
+
+      double m_massPi {};
+      double m_massP {};
+      double m_massE{};
+      double m_massK0{};
+      double m_massLam{};
+      std::string m_instanceName;
+
+//=======================================================================================
+// Functions and structure below are for algorithm development, debugging and calibration
+// NOT USED IN PRODUCTION!
+
+     int notFromBC(int PDGID) const;
+     const xAOD::TruthParticle * getPreviousParent(const xAOD::TruthParticle * child, int & ParentPDG) const;
+     int getIdHF(const xAOD::TrackParticle* TP ) const;
+     int getG4Inter( const xAOD::TrackParticle* TP ) const;
+     int getMCPileup(const xAOD::TrackParticle* TP ) const;
+
+     struct DevTuple 
+     { 
+       static const int maxNTrk=100;
+       static const int maxNVrt=100;
+       int   nTrk;
+       float pttrk[maxNTrk];
+       float Sig3D[maxNTrk];
+       int   n2Vrt;
+       int   VrtTrkHF[maxNVrt];
+       int   VrtTrkI[maxNVrt];
+       int   VrtCh[maxNVrt];
+       int   VrtIBL[maxNVrt];
+       int   VrtBL[maxNVrt];
+       int   VrtDisk[maxNVrt];
+       float VrtDist2D[maxNVrt];
+       float VrtSig3D[maxNVrt];
+       float VrtSig2D[maxNVrt];
+       float VrtM[maxNVrt];
+       float VrtZ[maxNVrt];
+       float VrtPt[maxNVrt];
+       float VrtEta[maxNVrt];
+       float VrtBDT[maxNVrt];
+       float VrtProb[maxNVrt];
+       float VrtHR1[maxNVrt];
+       float VrtHR2[maxNVrt];
+       float VrtSinSPM[maxNVrt];
+       float VMinPtT[maxNVrt];
+       float VMinS3DT[maxNVrt];
+       float VMaxS3DT[maxNVrt];
+       float VSigMat[maxNVrt];
+       //---
+       int   nNVrt;
+       int   NVrtTrk[maxNVrt];
+       int   NVrtTrkHF[maxNVrt];
+       int   NVrtTrkI[maxNVrt];
+       int   NVrtCh[maxNVrt];
+       int   NVrtIBL[maxNVrt];
+       int   NVrtBL[maxNVrt];
+       float NVrtM[maxNVrt];
+       float NVrtPt[maxNVrt];
+       float NVrtEta[maxNVrt];
+       float NVrtSinSPM[maxNVrt];
+       float NVMinPtT[maxNVrt];
+       float NVMinS3DT[maxNVrt];
+       float NVMaxS3DT[maxNVrt];
+       float NVrtDist2D[maxNVrt];
+       float NVrtSig3D[maxNVrt];
+       float NVrtSig2D[maxNVrt];
+       float NVrtProb[maxNVrt];
+       float NVrtBDT[maxNVrt];
+     };
+     DevTuple*  m_curTup;
+//
+// End of development stuff
+//============================================================
+
+
+     struct Vrt2Tr 
+     {   
+         int badVrt=0;
+         Amg::Vector3D     fitVertex;
+         TLorentzVector    momentum;
+         long int   vertexCharge;
+         std::vector<double> errorMatrix;
+         std::vector<double> chi2PerTrk;
+         std::vector< std::vector<double> > trkAtVrt;
+         double chi2=0.;
+         double dRSVPV=-1.;
+     };
+
+
+// For multivertex version only
+
+      boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS> *m_compatibilityGraph{};
+      float m_chiScale[11]{};
+      struct WrkVrt 
+     {   bool Good=true;
+         std::deque<long int> selTrk;
+         Amg::Vector3D     vertex;
+         TLorentzVector    vertexMom;
+         long int   vertexCharge{};
+         std::vector<double> vertexCov;
+         std::vector<double> chi2PerTrk;
+         std::vector< std::vector<double> > trkAtVrt;
+         double chi2{};
+         int nCloseVrt=0;
+         double dCloseVrt=1000000.;
+	 double projectedVrt=0.;
+         int detachedTrack=-1;
+      };
+
+
+//   Private technical functions
+//
+//
+      std::vector<xAOD::Vertex*> getVrtSecMulti(  workVectorArrxAOD * inpParticlesxAOD, const xAOD::Vertex  & primVrt) const;
+
+      void  trackClassification(std::vector<WrkVrt> *WrkVrtSet, 
+                                std::vector< std::deque<long int> > *TrkInVrt) const;
+
+      double maxOfShared(std::vector<WrkVrt> *WrkVrtSet, 
+                         std::vector< std::deque<long int> > *TrkInVrt,
+			 long int & selectedTrack,
+			 long int & selectedVertex) const;
+      void removeTrackFromVertex(std::vector<WrkVrt> *WrkVrtSet, 
+                                 std::vector< std::deque<long int> > *TrkInVrt,
+				 long int selectedTrack,
+				 long int selectedVertex) const;
+//
+//
+
+      void printWrkSet(const std::vector<WrkVrt> * WrkSet, const std::string &name ) const;
+
+//
+// Gives correct mass assignment in case of nonequal masses
+      double massV0(const std::vector< std::vector<double> >& TrkAtVrt, double massP, double massPi ) const;
+
+
+      TLorentzVector MomAtVrt(const std::vector<double>& inpTrk) const; 
+      double           VrtRadiusError(const Amg::Vector3D & secVrt, const std::vector<double>  & vrtErr) const;
+
+      int   nTrkCommon( std::vector<WrkVrt> *WrkVrtSet, int indexV1, int indexV2) const;
+      double minVrtVrtDist( std::vector<WrkVrt> *WrkVrtSet, int & indexV1, int & indexV2) const;
+      double minVrtVrtDistNext( std::vector<WrkVrt> *WrkVrtSet, int & indexV1, int & indexV2) const;
+      bool isPart( std::deque<long int> test, std::deque<long int> base) const;
+      void Clean1TrVertexSet(std::vector<WrkVrt> *WrkVrtSet) const;
+
+      double VrtVrtDist(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                                  const std::vector<double> VrtErr,double& Signif ) const;
+      double VrtVrtDist2D(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                                  const std::vector<double> VrtErr,double& Signif ) const;
+      double VrtVrtDist(const Amg::Vector3D & Vrt1, const std::vector<double>& VrtErr1,
+                        const Amg::Vector3D & Vrt2, const std::vector<double>& VrtErr2) const;
+      double VrtVrtDist(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                        const std::vector<double> SecVrtErr, const TLorentzVector & Dir) const;
+      double PntPntDist(const Amg::Vector3D & Vrt1, const Amg::Vector3D & Vrt2) const;
+
+      void DisassembleVertex(std::vector<WrkVrt> *WrkVrtSet, int iv, 
+                             std::vector<const xAOD::TrackParticle*>  AllTracks,
+                             Trk::IVKalState& istate) const;
+					  
+      double ProjSV_PV(const Amg::Vector3D & SV, const xAOD::Vertex & PV, const TLorentzVector & Direction) const;
+      double MomProjDist(const Amg::Vector3D & SV, const xAOD::Vertex & PV, const TLorentzVector & Direction) const;
+
+ 
+      double distToMatLayerSignificance(Vrt2Tr & Vrt) const;
+
+      StatusCode refitVertex( std::vector<WrkVrt> *WrkVrtSet, int SelectedVertex,
+                              std::vector<const xAOD::TrackParticle*> & SelectedTracks,
+                              Trk::IVKalState& istate,
+                              bool ifCovV0) const;
+
+      double refitVertex( WrkVrt &Vrt,std::vector<const xAOD::TrackParticle*> & SelectedTracks,
+                          Trk::IVKalState& istate,
+                          bool ifCovV0) const;
+ 
+      int mostHeavyTrk(WrkVrt V, std::vector<const xAOD::TrackParticle*> AllTracks) const;
+ 
+      double mergeAndRefitVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2, WrkVrt & newvrt,
+                                    std::vector<const xAOD::TrackParticle*> & AllTrackList,
+                                    Trk::IVKalState& istate) const;
+      void   mergeAndRefitOverlapVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2,
+                                           std::vector<const xAOD::TrackParticle*> & AllTrackLis,
+                                           Trk::IVKalState& istate) const;
+
+      double  improveVertexChi2( std::vector<WrkVrt> *WrkVrtSet, int V, std::vector<const xAOD::TrackParticle*> & AllTracks,
+                                 Trk::IVKalState& istate,
+                                 bool ifCovV0) const;
+
+      void selGoodTrkParticle( workVectorArrxAOD * xAODwrk,
+                               const xAOD::Vertex  & PrimVrt) const;
+
+
+
+      void select2TrVrt(std::vector<const xAOD::TrackParticle*>  & SelectedTracks,
+                        const xAOD::Vertex       & PrimVrt) const;
+
+
+     void  getPixelDiscs   (const xAOD::TrackParticle* Part, int &d0Hit, int &d1Hit, int &d2Hit) const;
+     int   getIBLHit(const xAOD::TrackParticle* Part) const;
+     int   getBLHit(const xAOD::TrackParticle* Part) const;
+
+   };
+
+
+  struct clique_visitor
+  {
+    clique_visitor(std::vector< std::vector<int> > & input): m_allCliques(input){ input.clear();}
+    
+    template <typename Clique, typename Graph>
+    void clique(const Clique& clq, Graph& )
+    { 
+      std::vector<int> new_clique(0);
+      for(auto i = clq.begin(); i != clq.end(); ++i) new_clique.push_back(*i);
+      m_allCliques.push_back(new_clique);
+    }
+
+    std::vector< std::vector<int> > & m_allCliques;
+
+  };
+
+
+}  //end namespace
+
+#endif
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/README b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/README
new file mode 100644
index 0000000000000000000000000000000000000000..fd65f5134f3eafe16e49c039be2f51d59b6c11f0
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/README
@@ -0,0 +1,28 @@
+A tool for inclusive secondary vertex reconstruction in ATLAS ID.
+
+This is an improved version of the VrtSecInclusive algorithm.
+
+Changes with respect to original version:
+
+1) Outdated Graph(CERNLIB) package is replaced by Bron&Kerbosch algorithm from BOOST
+2) Fake(fragmentation+pileup) and hadronic interaction vertices are removed using a dedicated MVA
+3) Additional material interaction rejection is based on the TrackingGeometry material layers
+4) Many improvements in vertex topology resolution
+5) One-track vertices are allowed (e.g. 3 track system, where one track crosses 2 others in different places, 
+     so that 3-track vertex has inacceptable Chi2, will be resolved as 2-track + 1-track vertices).
+     This allows to get 2 vertices in case of e.g. cascade B->D decay with 3 reconstracted tracks in total.
+6) Algorithm is converted to Tool for convenience of usage in other Algorithms.
+7) Several tool configurations suitable for different problems are provided, e.g.:
+        SoftBFinderTool         - targeting Soft b-tagging for SUSY
+	InclusiveBFinderTool    - inclusive B-hadron decay reconstruction (a la CMS/D0) for b-tagging
+	DVFinderTool            - search for displaced vertices produced by exotic particles  
+
+
+Configured finders:
+1) SoftBFinderTool       - looks for all low-pt (>1GeV) B-hadron vertices in event. No jet presence is assumed
+2) InclusiveBFinderTool  - looks for all B-hadron vertices in event with low fake rate. 
+                           Suitable for ttbar and other processes with similar pt-range.
+3) HighPtBFinderTool     - looks for all high-pt B-hadron vertices in event. No jet presence is assumed.
+4) MaterialSVFinderTool  - looks for hadronic interaction vertices in detector material.
+5) DVFinderTool          - looks for heavy displaced vertices in ID volume.
+   
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/python/NewVrtSecInclusive.py b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/python/NewVrtSecInclusive.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d3c3cebf3f28fb7f46810638800bbaac1ed6fe0
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/python/NewVrtSecInclusive.py
@@ -0,0 +1,189 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+# Author: Vadim Kostyukhin vadim.kostyukhin@cern.ch
+from GaudiKernel.GaudiHandles import *
+from GaudiKernel.Proxy.Configurable import *
+from AthenaCommon.Include  import Include, IncludeError, include
+from AthenaCommon.Logging  import logging
+from AthenaCommon.AppMgr   import ToolSvc
+from AthenaCommon          import CfgMgr
+
+from NewVrtSecInclusiveTool.NewVrtSecInclusiveToolConf import Rec__NewVrtSecInclusiveTool
+
+# define the class
+# Search for soft B-hadron vertices. 
+#------------------------------------
+class SoftBFinderTool( Rec__NewVrtSecInclusiveTool ):
+
+    def __init__(self, name = 'SoftBFinderTool'  ):        
+
+        from __main__ import ToolSvc
+        mlog = logging.getLogger( 'SoftBFinderTool::__init__ ' )
+        mlog.info("entering")
+        #----------------------
+        # VKalVrt vertex fitter
+        # 
+        from TrkVKalVrtFitter.TrkVKalVrtFitterConf import Trk__TrkVKalVrtFitter
+        SVertexFitterTool = Trk__TrkVKalVrtFitter(name="SoftBVertexFitterTool",
+                                                  Extrapolator="Trk::Extrapolator/AtlasExtrapolator")
+        ToolSvc += SVertexFitterTool
+        #----------------------
+        # Soft B-hadron vertex finder itself
+        #
+        Rec__NewVrtSecInclusiveTool.__init__( self, name = name,
+                                             VertexFitterTool   = SVertexFitterTool,
+					     CutBLayHits  = 1,
+					     CutPixelHits = 3,
+					     CutSiHits    = 8,
+					     useVertexCleaning  = True,
+					     MultiWithOneTrkVrt = True,
+					     removeTrkMatSignif = -1.,    # No additional material rejection
+					     AntiPileupSigRCut = 2.0,
+					     TrkSigCut         = 2.0,
+					     SelVrtSigCut      = 3.0,
+					     v2tIniBDTCut      =-0.6,
+					     v2tFinBDTCut      = 0.2,
+					     CutPt             = 500,
+					     MaxSVRadiusCut    = 50        # Inside Pixel BL volume
+                                             )
+        mlog = logging.getLogger( 'SoftBFinderTool::__configured__ ' )
+
+##########################################################################################################
+# define the class
+class InclusiveBFinderTool( Rec__NewVrtSecInclusiveTool ):
+
+    def __init__(self, name = 'InclusiveBFinderTool'  ):        
+
+        from __main__ import ToolSvc
+        mlog = logging.getLogger( 'InclusiveBFinderTool::__init__ ' )
+        mlog.info("entering")
+        #----------------------
+        # VKalVrt vertex fitter
+        # 
+        from TrkVKalVrtFitter.TrkVKalVrtFitterConf import Trk__TrkVKalVrtFitter
+        SVertexFitterTool = Trk__TrkVKalVrtFitter(name="InclsusiveBVertexFitterTool",
+                                                  Extrapolator="Trk::Extrapolator/AtlasExtrapolator")
+        ToolSvc += SVertexFitterTool
+        #----------------------
+        # Soft B-hadron vertex finder itself
+        #
+        Rec__NewVrtSecInclusiveTool.__init__( self, name = name,
+                                             VertexFitterTool   = SVertexFitterTool,
+					     CutBLayHits  = 0,
+					     CutPixelHits = 2,
+					     CutSiHits    = 8,
+					     useVertexCleaning  = True,
+					     MultiWithOneTrkVrt = True,
+					     removeTrkMatSignif = -1.,    # No additional material rejection
+					     AntiPileupSigRCut = 2.0,
+					     TrkSigCut         = 2.0,
+					     SelVrtSigCut      = 3.0,
+					     v2tIniBDTCut      =-0.5,
+					     v2tFinBDTCut      = 0.0,
+					     CutPt             = 500
+                                             )
+##########################################################################################################
+# define the class
+class HighPtBFinderTool( Rec__NewVrtSecInclusiveTool ):
+
+    def __init__(self, name = 'HighPtBFinderTool'  ):        
+
+        from __main__ import ToolSvc
+        mlog = logging.getLogger( 'HighPtBFinderTool::__init__ ' )
+        mlog.info("entering")
+        #----------------------
+        # VKalVrt vertex fitter
+        # 
+        from TrkVKalVrtFitter.TrkVKalVrtFitterConf import Trk__TrkVKalVrtFitter
+        SVertexFitterTool = Trk__TrkVKalVrtFitter(name="HighPtBVertexFitterTool",
+                                                  Extrapolator="Trk::Extrapolator/AtlasExtrapolator")
+        ToolSvc += SVertexFitterTool
+        #----------------------
+        # Soft B-hadron vertex finder itself
+        #
+        Rec__NewVrtSecInclusiveTool.__init__( self, name = name,
+                                             VertexFitterTool   = SVertexFitterTool,
+					     CutBLayHits  = 0,
+					     CutPixelHits = 2,
+					     CutSiHits    = 8,
+					     useVertexCleaning  = True,
+					     MultiWithOneTrkVrt = True,
+					     removeTrkMatSignif = -1.,    # No additional material rejection
+					     AntiPileupSigRCut = 2.0,
+					     TrkSigCut         = 2.0,
+					     SelVrtSigCut      = 3.0,
+					     v2tIniBDTCut      =-0.6,
+					     v2tFinBDTCut      = 0.2,
+					     CutPt             = 1000
+                                             )
+##########################################################################################################
+# define the class
+class MaterialSVFinderTool( Rec__NewVrtSecInclusiveTool ):
+
+    def __init__(self, name = 'MaterialSVFinderTool'  ):        
+
+        from __main__ import ToolSvc
+        mlog = logging.getLogger( 'MaterialSVFinderTool::__init__ ' )
+        mlog.info("entering")
+        #----------------------
+        # VKalVrt vertex fitter
+        # 
+        from TrkVKalVrtFitter.TrkVKalVrtFitterConf import Trk__TrkVKalVrtFitter
+        SVertexFitterTool = Trk__TrkVKalVrtFitter(name="MaterialSVVertexFitterTool",
+                                                  Extrapolator="Trk::Extrapolator/AtlasExtrapolator")
+        ToolSvc += SVertexFitterTool
+        #----------------------
+        # Soft B-hadron vertex finder itself
+        #
+        Rec__NewVrtSecInclusiveTool.__init__( self, name = name,
+                                             VertexFitterTool   = SVertexFitterTool,
+					     CutBLayHits  = 0,
+					     CutPixelHits = 1,
+					     CutSiHits    = 8,
+					     useVertexCleaning  = False,
+					     MultiWithOneTrkVrt = False,
+					     removeTrkMatSignif = -1.,    # No additional material rejection
+					     AntiPileupSigRCut = 5.0,
+					     TrkSigCut         = 5.0,
+					     SelVrtSigCut      = 10.0,
+					     v2tIniBDTCut      =-10.,     #Effectively remove MVA selection
+					     v2tFinBDTCut      =-10.,     #Effectively remove MVA selection
+					     VrtMassLimit      = 8000.,
+					     Vrt2TrMassLimit   = 8000.,
+					     CutPt             = 500.
+                                             )
+##########################################################################################################
+# define the class
+class DVFinderTool( Rec__NewVrtSecInclusiveTool ):
+
+    def __init__(self, name = 'DVFinderTool'  ):        
+
+        from __main__ import ToolSvc
+        mlog = logging.getLogger( 'DVFinderTool::__init__ ' )
+        mlog.info("entering")
+        #----------------------
+        # VKalVrt vertex fitter
+        # 
+        from TrkVKalVrtFitter.TrkVKalVrtFitterConf import Trk__TrkVKalVrtFitter
+        DVertexFitterTool = Trk__TrkVKalVrtFitter(name="DVertexFitterTool",
+                                                  Extrapolator="Trk::Extrapolator/AtlasExtrapolator")
+        ToolSvc += DVertexFitterTool
+        #----------------------
+        # Soft B-hadron vertex finder itself
+        #
+        Rec__NewVrtSecInclusiveTool.__init__( self, name = name,
+                                             VertexFitterTool   = SVertexFitterTool,
+					     CutBLayHits  = 0,
+					     CutPixelHits = 0,
+					     CutSiHits    = 0,
+					     useVertexCleaning  = False,
+					     MultiWithOneTrkVrt = False,
+					     removeTrkMatSignif = 2.,
+					     AntiPileupSigRCut = 6.0,
+					     TrkSigCut         = 6.0,
+					     SelVrtSigCut      = 8.0,
+					     v2tIniBDTCut      =-0.5,
+					     v2tFinBDTCut      = 0.0,
+					     VrtMassLimit      = 50000.,
+					     Vrt2TrMassLimit   = 50000.,
+					     CutPt             = 1000.
+                                             )
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/CutTrk.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/CutTrk.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..122b6f0574f8e4cfeaa8a00b0afa3438b6661852
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/CutTrk.cxx
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///   @author   V.Kostykhin <Vadim.Kostyukhin@cern.ch>
+/// 
+
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+#include  "AnalysisUtils/AnalysisMisc.h"
+#include  "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+
+#include "TH1.h"
+
+//-------------------------------------------------
+namespace Rec{
+
+
+//==============================================================================================================
+//          xAOD based stuff
+//
+   void NewVrtSecInclusiveTool::selGoodTrkParticle( workVectorArrxAOD * xAODwrk,
+                                                    const xAOD::Vertex & PrimVrt)
+   const
+   {    
+    std::vector<const xAOD::TrackParticle*>& inpTrk          = xAODwrk->inpTrk;
+    std::vector<const xAOD::TrackParticle*>& selectedTracks  = xAODwrk->listSelTracks;
+    std::vector<const xAOD::TrackParticle*>::const_iterator   i_ntrk;
+    std::vector<double> impact,impactError;
+    std::multimap<double,const xAOD::TrackParticle*> orderedTrk;
+    if(m_fillHist){ m_hb_ntrkInput->Fill( inpTrk.size()+0.1, m_w_1);}
+    for (i_ntrk = inpTrk.begin(); i_ntrk < inpTrk.end(); ++i_ntrk) {
+//
+//-- Perigee in TrackParticle
+//
+          if(m_fillHist){ m_hb_trkSelect->Fill( 0., m_w_1);}
+          if((*i_ntrk)->numberDoF() == 0) continue; //Protection
+          double trkChi2 = (*i_ntrk)->chiSquared() / (*i_ntrk)->numberDoF();
+          if(trkChi2 	      > m_cutChi2)           continue;
+          if( (*i_ntrk)->pt()  < m_cutPt)            continue;
+          if(m_fillHist){ m_hb_trkSelect->Fill( 1., m_w_1);}
+ 
+          const Trk::Perigee mPer=(*i_ntrk)->perigeeParameters() ;
+          double CovTrkMtx00 = (*(mPer.covariance()))(0,0);
+ 
+          uint8_t PixelHits,SctHits,BLayHits;
+          if( !((*i_ntrk)->summaryValue(PixelHits,xAOD::numberOfPixelHits)) )   continue; // Track is 
+          if( !((*i_ntrk)->summaryValue(  SctHits,xAOD::numberOfSCTHits))   )   continue; // definitely  
+          if( SctHits<3 )                                                       continue; // bad
+          if( !((*i_ntrk)->summaryValue(BLayHits,xAOD::numberOfInnermostPixelLayerHits)))  BLayHits=0;
+          if(m_fillHist){ m_hb_trkSelect->Fill( 2., m_w_1);}
+
+          uint8_t splSCTHits,outSCTHits,splPixHits,outPixHits;
+          if( !((*i_ntrk)->summaryValue(splSCTHits,xAOD::numberOfSCTSpoiltHits)))  splSCTHits=0;
+          if( !((*i_ntrk)->summaryValue(outSCTHits,xAOD::numberOfSCTOutliers)))    outSCTHits=0;
+          if( !((*i_ntrk)->summaryValue(splPixHits,xAOD::numberOfPixelSpoiltHits)))splPixHits=0;
+          if( !((*i_ntrk)->summaryValue(outPixHits,xAOD::numberOfPixelOutliers)))  outPixHits=0;
+
+          Amg::Vector3D perigeePos=mPer.position();
+          double impactA0=sqrt( (perigeePos.x()-PrimVrt.x())*(perigeePos.x()-PrimVrt.x())
+                               +(perigeePos.y()-PrimVrt.y())*(perigeePos.y()-PrimVrt.y()) );
+          double impactZ=perigeePos.z()-PrimVrt.z();
+          if(m_fillHist){  
+            m_hb_trkD0->Fill( impactA0, m_w_1);
+            m_hb_trkZ ->Fill( impactZ, m_w_1);
+          }
+          if(fabs(impactZ)>m_cutZVrt) continue;
+          if(impactA0>m_cutA0)        continue;
+          if(m_fillHist){ m_hb_trkSelect->Fill( 3., m_w_1);}
+     
+          double bX=xAODwrk->beamX + (perigeePos.z()-xAODwrk->beamZ)*xAODwrk->tanBeamTiltX;
+          double bY=xAODwrk->beamY + (perigeePos.z()-xAODwrk->beamZ)*xAODwrk->tanBeamTiltY;
+          double impactBeam=sqrt( (perigeePos.x()-bX)*(perigeePos.x()-bX) + (perigeePos.y()-bY)*(perigeePos.y()-bY));
+//----Anti-pileup
+          double signifBeam = impactBeam    / sqrt(CovTrkMtx00);
+          if(signifBeam < m_antiPileupSigRCut) continue;   // cut against tracks from pileup vertices
+          if(m_fillHist){ m_hb_trkSelect->Fill( 4., m_w_1);}
+//----
+          if(PixelHits	    < m_cutPixelHits) 		continue;
+          if(SctHits	    < m_cutSctHits) 		continue;
+          if((PixelHits+SctHits) < m_cutSiHits) 	continue;
+          if(BLayHits	    < m_cutBLayHits) 		continue;
+          if(m_fillHist){ m_hb_trkSelect->Fill( 5., m_w_1);}
+//----
+          orderedTrk.emplace(signifBeam,*i_ntrk);
+          selectedTracks.push_back(*i_ntrk);
+      }
+//---- Order tracks according to pt
+//      AnalysisUtils::Sort::pT (selectedTracks)     
+//---- Order tracks according to ranks
+      std::map<double,const xAOD::TrackParticle*>::reverse_iterator rt=orderedTrk.rbegin();
+      selectedTracks.resize(orderedTrk.size());
+      for ( int cntt=0; rt!=orderedTrk.rend(); ++rt,++cntt) {selectedTracks[cntt]=(*rt).second;}
+      return;
+   }
+
+}//end namespace
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/MultiUtilities.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/MultiUtilities.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..7d7378aa8d226712c63b87a7d4da00dafdf0fdb5
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/MultiUtilities.cxx
@@ -0,0 +1,620 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///     @author Vadim Kostyukhin <vadim.kostyukhin@cern.ch>
+///
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+//-------------------------------------------------
+// Other stuff
+#include  "AnalysisUtils/AnalysisMisc.h"
+#include  "GeoPrimitives/GeoPrimitivesHelpers.h"
+#include  "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+#include  "TMath.h"
+#include  <algorithm>
+//
+
+
+namespace Rec{
+
+
+                      /* Service routines*/
+
+//-----------------------------------------------------------------------------------
+//  Find track contributing most to the vertex invariant mass
+   int NewVrtSecInclusiveTool::mostHeavyTrk(WrkVrt V, std::vector<const xAOD::TrackParticle*> AllTracks)
+   const
+   {
+      int NTrk=V.selTrk.size(), SelT=-1;
+      if(NTrk<3)return -1;
+//--------------------------------------------------
+      TLorentzVector TSum;
+      for(int i=0; i<NTrk; i++){
+         TSum += AllTracks.at(V.selTrk[i])->p4();
+      }
+      double massMin=1.e9;
+      for(int i=0; i<NTrk; i++){
+         TLorentzVector TSum_m1 = TSum - AllTracks[V.selTrk[i]]->p4();
+         if(TSum_m1.M()<massMin){massMin=TSum_m1.M(); SelT=i;}
+      }
+      return SelT;
+    }
+//-----------------------------------------------------------------------------------
+//  Detach the worst Chi2 track from the vertex and join it (if possible) with other track 
+//    from the vertex into additional 2-track vertices
+//
+   void NewVrtSecInclusiveTool::DisassembleVertex(std::vector<WrkVrt> *WrkVrtSet, int iv, 
+                                                std::vector<const xAOD::TrackParticle*>  AllTracks,
+                                                Trk::IVKalState& istate)
+   const
+   {
+      WrkVrt newvrt; newvrt.Good=true;
+      int NTrk=(*WrkVrtSet)[iv].selTrk.size(), SelT=-1;
+      if(NTrk<3)return;
+
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      std::vector<const xAOD::TrackParticle*>  ListBaseTracks;
+      StatusCode sc; sc.setChecked();
+//=== To get robust definition of most bad outlier
+      m_fitSvc->setRobustness(5, istate);
+      sc = refitVertex( WrkVrtSet, iv, AllTracks, istate, false);
+      if(sc.isFailure()){ (*WrkVrtSet)[iv].Good=false; return; }
+      m_fitSvc->setRobustness(0, istate);
+//--------------------------------------------------
+      double Chi2Max=0.;
+      for(int i=0; i<NTrk; i++){
+         if( (*WrkVrtSet)[iv].chi2PerTrk[i]>Chi2Max) { Chi2Max=(*WrkVrtSet)[iv].chi2PerTrk[i];  SelT=i;}
+      }	    
+      int NVrtCur=WrkVrtSet->size();
+      for(int i=0; i<NTrk; i++){
+	   if(i==SelT)continue;
+           ListBaseTracks.clear();
+	   ListBaseTracks.push_back( AllTracks[(*WrkVrtSet)[iv].selTrk[i]] );
+	   ListBaseTracks.push_back( AllTracks[(*WrkVrtSet)[iv].selTrk[SelT]] );
+           newvrt.selTrk.resize(2); 
+	   newvrt.selTrk[0]=(*WrkVrtSet)[iv].selTrk[i]; 
+	   newvrt.selTrk[1]=(*WrkVrtSet)[iv].selTrk[SelT];
+           sc = m_fitSvc->VKalVrtFitFast(ListBaseTracks,newvrt.vertex,istate);            /* Fast crude estimation*/
+           if( sc.isFailure() )  continue;
+           if( newvrt.vertex.perp() > m_maxSVRadiusCut )  newvrt.vertex=Amg::Vector3D(0.,0.,0.);
+           m_fitSvc->setApproximateVertex(newvrt.vertex[0],newvrt.vertex[1],newvrt.vertex[2],istate);
+           sc=m_fitSvc->VKalVrtFit(ListBaseTracks, neutralPartDummy,
+                             newvrt.vertex,
+                             newvrt.vertexMom,
+                             newvrt.vertexCharge,
+                             newvrt.vertexCov,
+                             newvrt.chi2PerTrk, 
+                             newvrt.trkAtVrt,
+                             newvrt.chi2,
+                             istate, false);
+           if( sc.isFailure() )  continue;  
+           if( newvrt.chi2>10.)  continue;  // Too bad 2-track vertex fit
+           newvrt.chi2PerTrk[0]=newvrt.chi2PerTrk[1]=newvrt.chi2/2.;
+           newvrt.nCloseVrt    = 0;
+           newvrt.dCloseVrt    = 1000000.;
+           newvrt.projectedVrt = 0.9999;
+           if((int)WrkVrtSet->size()==NVrtCur) { WrkVrtSet->push_back(newvrt); continue;}  // just the first added vertex
+           if( (*WrkVrtSet).at(NVrtCur).chi2<newvrt.chi2 ) continue;  // previously added 2tr vertex was better
+           WrkVrtSet->pop_back();
+           WrkVrtSet->push_back(newvrt);
+      }
+      (*WrkVrtSet)[iv].selTrk.erase( (*WrkVrtSet)[iv].selTrk.begin() + SelT ); //remove track
+      sc = refitVertex( WrkVrtSet, iv, AllTracks, istate, false);
+      if( sc.isFailure() ) {(*WrkVrtSet)[iv].Good=false; /*std::cout<<" Wrong vertex"<<'\n';*/}
+   }
+
+
+   void NewVrtSecInclusiveTool::Clean1TrVertexSet(std::vector<WrkVrt> *WrkVrtSet)
+   const
+   {
+     std::vector<int> countVT(WrkVrtSet->size(),0);
+     std::vector<int> linkedVrt(WrkVrtSet->size(),0);
+//--- Mark as bad the 1track vertex if the detached track is NOT present in any remaining good vertex (>=2tr)    
+     for(int i1tv=0; i1tv<(int)WrkVrtSet->size(); i1tv++) {
+       if( (*WrkVrtSet)[i1tv].selTrk.size()!=1) continue;
+       if(!(*WrkVrtSet)[i1tv].Good)             continue;   
+       int Trk1=(*WrkVrtSet)[i1tv].detachedTrack; 
+       int foundInGoodVrt=0;
+       for(int mtv=0; mtv<(int)WrkVrtSet->size(); mtv++) {                        //cycle over good vertices with many tracks
+         if( (*WrkVrtSet)[mtv].selTrk.size()<2) continue;
+	 if(!(*WrkVrtSet)[mtv].Good)            continue;   
+         if( std::find((*WrkVrtSet)[mtv].selTrk.begin(),(*WrkVrtSet)[mtv].selTrk.end(), Trk1) != (*WrkVrtSet)[mtv].selTrk.end()){
+           //double m2Vrt=((*WrkVrtSet)[mtv].vertexMom+(*WrkVrtSet)[i1tv].vertexMom).M(); //VK Commented.  M cut in other places
+           //if(m2Vrt>m_VrtMassLimit){ (*WrkVrtSet)[i1tv].Good=false;  break; } //1Tr + manyTr system is too heavy
+	   foundInGoodVrt++; countVT[mtv]++; linkedVrt[i1tv]=mtv;  //Linked vertex found
+         }
+       }
+       if(!foundInGoodVrt)(*WrkVrtSet)[i1tv].Good=false;             // Make the vertex bad
+     }
+//
+//---Select SINGLE 1tr-vertex from many pointing to one multi-track vertex
+     for(int mtv=0; mtv<(int)WrkVrtSet->size(); mtv++) {
+       if( (*WrkVrtSet)[mtv].selTrk.size()<2 ) continue;
+       if(!(*WrkVrtSet)[mtv].Good )            continue;   
+       if(      countVT[mtv] < 1 )             continue;
+       double distM=1.e9;
+       int    best1TVrt=-1;
+       for(int i1tv=0; i1tv<(int)WrkVrtSet->size(); i1tv++) {
+         if( (*WrkVrtSet)[i1tv].selTrk.size()!=1 ) continue;
+         if(!(*WrkVrtSet)[i1tv].Good )             continue;   
+	 if( linkedVrt[i1tv] != mtv )              continue;
+         //double dist=((*WrkVrtSet)[mtv].vertex - (*WrkVrtSet)[i1tv].vertex).mag();
+         double dist=((*WrkVrtSet)[mtv].vertexMom+(*WrkVrtSet)[i1tv].vertexMom).M(); //Use 
+         if( dist < distM ) {distM=dist; best1TVrt=i1tv;}
+         (*WrkVrtSet)[i1tv].Good=false;   
+       }
+       if(best1TVrt>-1 && distM<m_VrtMassLimit)(*WrkVrtSet)[best1TVrt].Good=true;
+     }
+   }
+   
+   
+   void NewVrtSecInclusiveTool::trackClassification(std::vector<WrkVrt> *WrkVrtSet, 
+                                             std::vector< std::deque<long int> > *TrkInVrt)
+   const
+   { 
+      int NSet=WrkVrtSet->size(); 
+      for(int iv=0; iv<NSet; iv++) {
+         if(!(*WrkVrtSet)[iv].Good) continue;
+         int NTrkAtVrt=(*WrkVrtSet)[iv].selTrk.size();
+         if(NTrkAtVrt<2) continue;
+         for(int jt=0; jt<NTrkAtVrt; jt++){
+           int tracknum=(*WrkVrtSet)[iv].selTrk[jt];
+	   (*TrkInVrt).at(tracknum).push_back(iv);
+         }
+      }
+   }
+
+
+   double NewVrtSecInclusiveTool::maxOfShared(std::vector<WrkVrt> *WrkVrtSet, 
+                                       std::vector< std::deque<long int> > *TrkInVrt,
+				       long int & SelectedTrack,
+				       long int & SelectedVertex)
+   const
+   {
+      long int NTrack=TrkInVrt->size(); 
+      int it, jv, itmp, NVrt, VertexNumber;
+ 
+      double MaxOf=-999999999, Chi2Red=0., SelectedProb=1.;
+//
+      int NShareMax=0;
+      for( it=0; it<NTrack; it++) {
+         NVrt=(*TrkInVrt)[it].size();         /*Number of vertices for this track*/
+         if(  NVrt > NShareMax ) NShareMax=NVrt;
+      }
+      if(NShareMax<=1)return MaxOf;              /* No shared tracks */
+//      
+      for( it=0; it<NTrack; it++) {
+         NVrt=(*TrkInVrt)[it].size();         /*Number of vertices for this track*/
+         if(  NVrt <= 1 )        continue;    /*Should ALWAYS be checked for safety*/
+         if(  NVrt < NShareMax ) continue;    /*Not a shared track with maximal sharing*/
+         double maxRadius=0;
+         for(auto &vrtn :(*TrkInVrt)[it] ){ maxRadius=std::max((*WrkVrtSet).at(vrtn).vertex.perp(),maxRadius); } //count number of 2-track vertices
+         for( jv=0; jv<NVrt; jv++ ){
+	    VertexNumber=(*TrkInVrt)[it][jv];
+	    if(!(*WrkVrtSet).at(VertexNumber).Good)continue;
+	    int NTrkInVrt=(*WrkVrtSet)[VertexNumber].selTrk.size();
+	    if( NTrkInVrt <= 1) continue;                                // one track vertex - nothing to do
+            ////if( N2trVrt>0 && N2trVrt<NShareMax && NTrkInVrt>2) continue; // Mixture of multi-track and 2-track vrts. Skip multi-track then.??? Bad!!!
+	    for( itmp=0; itmp<NTrkInVrt; itmp++){
+	       if( (*WrkVrtSet)[VertexNumber].selTrk[itmp] == it ) {         /* Track found*/        
+	          //Chi2Red=(*WrkVrtSet)[VertexNumber].chi2PerTrk.at(itmp);            //   Normal Chi2 
+	          Chi2Red=(*WrkVrtSet)[VertexNumber].chi2PerTrk.at(itmp)*(*WrkVrtSet)[VertexNumber].vertex.perp()/maxRadius; // Works much better
+                  double prob_vrt = TMath::Prob( (*WrkVrtSet)[VertexNumber].chi2, 2*(*WrkVrtSet)[VertexNumber].selTrk.size()-3);
+                  if( MaxOf < Chi2Red ){
+		      if(MaxOf>0 && prob_vrt>0.01 && SelectedProb<0.01 ) continue; // Don't disassemble good vertices if a bad one is present
+		      MaxOf = Chi2Red;
+		      SelectedTrack=it; SelectedVertex=VertexNumber;
+                      SelectedProb = prob_vrt;
+		  }
+               }
+            }
+	 }
+      }
+//-- Additional check for a common track in 2tr-2tr/Ntr vertex topology
+      if( (*TrkInVrt)[SelectedTrack].size() == 2){
+          int v1=(*TrkInVrt)[SelectedTrack][0]; int v2=(*TrkInVrt)[SelectedTrack][1];
+          double prb1=TMath::Prob( (*WrkVrtSet)[v1].chi2, 2*(*WrkVrtSet)[v1].selTrk.size()-3),
+                 prb2=TMath::Prob( (*WrkVrtSet)[v2].chi2, 2*(*WrkVrtSet)[v2].selTrk.size()-3);
+	  double dst1=(*WrkVrtSet)[v1].projectedVrt, dst2=(*WrkVrtSet)[v2].projectedVrt; 
+          if(prb1>0.05 && prb2>0.05){
+            if( (*WrkVrtSet)[v1].selTrk.size()==2 && (*WrkVrtSet)[v2].selTrk.size()==2){
+              if     (SelectedVertex==v1 && dst2<dst1)  SelectedVertex=v2;  // Swap to remove the closest to PV vertex
+              else if(SelectedVertex==v2 && dst1<dst2)  SelectedVertex=v1;  // Swap to remove the closest to PV vertex
+              double M1=(*WrkVrtSet)[v1].vertexMom.M();  double M2=(*WrkVrtSet)[v2].vertexMom.M();
+              if( M1>m_VrtMassLimit && M2<m_VrtMassLimit ) SelectedVertex=v1;
+              if( M1<m_VrtMassLimit && M2>m_VrtMassLimit ) SelectedVertex=v2;
+            }
+            if( (*WrkVrtSet)[v1].selTrk.size()+(*WrkVrtSet)[v2].selTrk.size() > 4){
+	       if( (*WrkVrtSet)[v1].selTrk.size()==2 && dst1>dst2) SelectedVertex=v2;
+	       if( (*WrkVrtSet)[v2].selTrk.size()==2 && dst2>dst1) SelectedVertex=v1;
+          } }	
+      }
+//
+      return MaxOf;
+   }
+
+
+   void NewVrtSecInclusiveTool::removeTrackFromVertex(std::vector<WrkVrt> *WrkVrtSet, 
+                                       std::vector< std::deque<long int> > *TrkInVrt,
+				       long int selectedTrack,
+				       long int selectedVertex)
+   const
+   {   
+        int posInVrtFit=0;                    //Position of SelectedTrack in vertex fit track list.
+	std::deque<long int>::iterator it;
+        WrkVrt & CVRT=(*WrkVrtSet).at(selectedVertex);
+//std::cout<<" In Found ="<<selectedTrack<<", "<<selectedVertex<<'\n';
+	for(it=CVRT.selTrk.begin(); 
+	    it!=CVRT.selTrk.end();     it++) {
+	    if( (*it) == selectedTrack ) { 
+	       CVRT.selTrk.erase(it); break;
+	    }     
+            posInVrtFit++;
+	}   
+
+	for(it=(*TrkInVrt).at(selectedTrack).begin(); 
+	    it!=(*TrkInVrt)[selectedTrack].end();     it++) {
+	    if( (*it) == selectedVertex ) { 
+	       (*TrkInVrt)[selectedTrack].erase(it); break;
+	    }     
+	}   
+        (*WrkVrtSet)[selectedVertex].detachedTrack=selectedTrack;
+//Check if track is removed from 2tr vertex => then sharing of track left should also be decreased
+        if( CVRT.selTrk.size() == 1){
+	   long int LeftTrack=CVRT.selTrk[0];  // track left in 1tr vertex
+	   for(it=(*TrkInVrt).at(LeftTrack).begin();  it!=(*TrkInVrt)[LeftTrack].end();  it++) {
+	      if( (*it) == selectedVertex ) { 
+	       (*TrkInVrt)[LeftTrack].erase(it); break;
+	      }     
+	   }   
+           if( TMath::Prob( CVRT.chi2, 1) < 0.05 ) CVRT.Good=false; // Not really good Chi2 for one-track vertex
+	   if( CVRT.vertexMom.M()>m_VrtMassLimit)CVRT.Good=false;   // Vertex is too heavy
+           int ipos=0; if(posInVrtFit==0)ipos=1;                    // Position of remaining track in previous 2track vertex fit
+	   CVRT.vertexMom=MomAtVrt(CVRT.trkAtVrt[ipos]);            //Redefine vertexMom using remaining track
+	   if((*TrkInVrt)[LeftTrack].size()>0)CVRT.Good=false;      //Vertex is declared false only if remaining track 
+	    						            // is still linked to another vertex
+           if(CVRT.vertexMom.Pt()<2.*m_cutPt) CVRT.Good=false;      //1track vertex should have twice momentum of track pt cut
+	   CVRT.trkAtVrt.erase((*WrkVrtSet)[selectedVertex].trkAtVrt.begin()+posInVrtFit);  //Remove also TrkAtVrt
+        }
+
+   }
+//
+//  Number of common tracks for 2 vertices
+//
+   int NewVrtSecInclusiveTool::nTrkCommon( std::vector<WrkVrt> *WrkVrtSet, 
+                                         int V1, int V2)
+   const
+   {
+      int NTrk_V1 = (*WrkVrtSet).at(V1).selTrk.size(); if( NTrk_V1< 2) return 0;   /* Bad vertex */
+      int NTrk_V2 = (*WrkVrtSet).at(V2).selTrk.size(); if( NTrk_V2< 2) return 0;   /* Bad vertex */
+      int nTrkCom=0;
+      if(NTrk_V1 < NTrk_V2){
+        for(int i=0; i<NTrk_V1; i++){
+          int trk=(*WrkVrtSet)[V1].selTrk[i];
+          if( std::find((*WrkVrtSet)[V2].selTrk.begin(),(*WrkVrtSet)[V2].selTrk.end(),trk) != (*WrkVrtSet)[V2].selTrk.end()) nTrkCom++;
+        }
+      }else{
+        for(int i=0; i<NTrk_V2; i++){
+          int trk=(*WrkVrtSet)[V2].selTrk[i];
+          if( std::find((*WrkVrtSet)[V1].selTrk.begin(),(*WrkVrtSet)[V1].selTrk.end(),trk) != (*WrkVrtSet)[V1].selTrk.end()) nTrkCom++;
+        }
+      }
+      return nTrkCom;
+   }
+//
+//  Minimal normalized vertex-vertex distance
+//
+   double NewVrtSecInclusiveTool::minVrtVrtDist( std::vector<WrkVrt> *WrkVrtSet, int & V1, int & V2)
+   const
+   {  
+     V1=V2=0;
+     for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) { (*WrkVrtSet).at(iv).dCloseVrt=1000000.; (*WrkVrtSet)[iv].nCloseVrt=-1;}
+     double foundMinVrtDst=1000000.;
+
+     for(int iv=0; iv<(int)WrkVrtSet->size()-1; iv++) {
+        if( (*WrkVrtSet)[iv].selTrk.size()< 2)    continue;   /* Bad vertices */
+        if(!(*WrkVrtSet)[iv].Good )               continue;   /* Bad vertices */
+        for(int jv=iv+1; jv<(int)WrkVrtSet->size(); jv++) {
+           if( (*WrkVrtSet)[jv].selTrk.size()< 2) continue;   /* Bad vertices */
+           if(!(*WrkVrtSet)[jv].Good )            continue;   /* Bad vertices */
+           //if(!nTrkCommon(WrkVrtSet, V1, V2))     continue;   /* No common tracks*/
+           double tmp= fabs((*WrkVrtSet)[iv].vertex.x()-(*WrkVrtSet)[jv].vertex.x())
+                      +fabs((*WrkVrtSet)[iv].vertex.y()-(*WrkVrtSet)[jv].vertex.y())
+                      +fabs((*WrkVrtSet)[iv].vertex.z()-(*WrkVrtSet)[jv].vertex.z());
+           if(tmp>20.) continue;
+           double tmpDst = VrtVrtDist((*WrkVrtSet)[iv].vertex,(*WrkVrtSet)[iv].vertexCov,
+                                      (*WrkVrtSet)[jv].vertex,(*WrkVrtSet)[jv].vertexCov);
+           if( tmpDst < foundMinVrtDst){foundMinVrtDst = tmpDst; V1=iv; V2=jv;} 
+           if( tmpDst < (*WrkVrtSet)[iv].dCloseVrt ) {(*WrkVrtSet)[iv].dCloseVrt=tmpDst; (*WrkVrtSet)[iv].nCloseVrt=jv;}
+           if( tmpDst < (*WrkVrtSet)[jv].dCloseVrt ) {(*WrkVrtSet)[jv].dCloseVrt=tmpDst; (*WrkVrtSet)[jv].nCloseVrt=iv;}
+         }
+      }
+      return foundMinVrtDst;
+   }
+//   
+// Give minimal distance between nonmodifed yet vertices
+//   
+   double NewVrtSecInclusiveTool::minVrtVrtDistNext( std::vector<WrkVrt> *WrkVrtSet, int & V1, int & V2)
+   const
+   {  
+     V1=0; V2=0;
+     double foundMinVrtDst=1000000.;
+     for(int iv=0; iv<(int)WrkVrtSet->size()-1; iv++) {
+        if( (*WrkVrtSet)[iv].selTrk.size()< 2) continue;   /* Bad vertex */
+        if( (*WrkVrtSet)[iv].nCloseVrt==-1)    continue;   /* Used vertex */
+        if( (*WrkVrtSet)[iv].dCloseVrt <foundMinVrtDst ) {
+	   int vtmp=(*WrkVrtSet)[iv].nCloseVrt;
+           if((*WrkVrtSet)[vtmp].nCloseVrt==-1) { continue;}  // Close vertex to given [iv] one is modified already 
+	   foundMinVrtDst=(*WrkVrtSet)[iv].dCloseVrt;
+	   V1=iv;
+	   V2=vtmp;
+	}
+      }
+      return foundMinVrtDst;
+   }
+
+//
+//  Check two close vertices by explicit vertex fit and create combined vertex if successful
+//
+   double  NewVrtSecInclusiveTool::mergeAndRefitVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2, WrkVrt & newvrt,
+                                                        std::vector<const xAOD::TrackParticle*> & AllTrackList,
+                                                        Trk::IVKalState& istate)
+   const
+   {
+      if(!(*WrkVrtSet).at(V1).Good)return -1.;         //bad vertex
+      if(!(*WrkVrtSet).at(V2).Good)return -1.;         //bad vertex
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      newvrt.Good=true;
+      int NTrk_V1=(*WrkVrtSet)[V1].selTrk.size();
+      int NTrk_V2=(*WrkVrtSet)[V2].selTrk.size();
+      newvrt.selTrk.resize(NTrk_V1+NTrk_V2);
+      std::copy((*WrkVrtSet)[V1].selTrk.begin(),(*WrkVrtSet)[V1].selTrk.end(), newvrt.selTrk.begin());
+      std::copy((*WrkVrtSet)[V2].selTrk.begin(),(*WrkVrtSet)[V2].selTrk.end(), newvrt.selTrk.begin()+NTrk_V1);
+
+      std::deque<long int>::iterator   TransfEnd ;
+      sort( newvrt.selTrk.begin(), newvrt.selTrk.end() );
+      TransfEnd =  unique( newvrt.selTrk.begin(), newvrt.selTrk.end() );
+      newvrt.selTrk.erase( TransfEnd, newvrt.selTrk.end());
+      std::vector<const xAOD::TrackParticle*>  fitTrackList(0);
+      for(int it=0; it<(int)newvrt.selTrk.size(); it++)fitTrackList.push_back( AllTrackList[newvrt.selTrk[it]] );
+      m_fitSvc->setApproximateVertex( 0.5*((*WrkVrtSet)[V1].vertex[0]+(*WrkVrtSet)[V2].vertex[0]),
+                                      0.5*((*WrkVrtSet)[V1].vertex[1]+(*WrkVrtSet)[V2].vertex[1]),
+                                      0.5*((*WrkVrtSet)[V1].vertex[2]+(*WrkVrtSet)[V2].vertex[2]),
+                                      istate);
+      
+      StatusCode sc=m_fitSvc->VKalVrtFit(fitTrackList,neutralPartDummy,
+                                   newvrt.vertex, newvrt.vertexMom, newvrt.vertexCharge, newvrt.vertexCov,
+                                   newvrt.chi2PerTrk,  newvrt.trkAtVrt, newvrt.chi2,
+                                   istate, false);
+      if( sc.isFailure() )             return -1.;  
+      if( newvrt.chi2>500. )           return -1.;  //VK protection
+      if( newvrt.chi2PerTrk.size()==2) newvrt.chi2PerTrk[0]=newvrt.chi2PerTrk[1]=newvrt.chi2/2.;
+      return TMath::Prob( newvrt.chi2, 2*newvrt.selTrk.size()-3);
+   }
+   //
+   //
+   //================== Intelligent merge of multitrack vertices with 2 and more common tracks
+   void  NewVrtSecInclusiveTool::mergeAndRefitOverlapVertices( std::vector<WrkVrt> *WrkVrtSet, int V1, int V2,
+                                                             std::vector<const xAOD::TrackParticle*> & AllTrackList,
+                                                             Trk::IVKalState& istate) const
+   {
+      if(!(*WrkVrtSet).at(V1).Good)return;         //bad vertex
+      if(!(*WrkVrtSet).at(V2).Good)return;         //bad vertex
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      WrkVrt newvrt;
+      newvrt.Good=true;
+      if( nTrkCommon( WrkVrtSet, V1, V2)<2 )return;       //No overlap
+      //- V1 should become ref. vertex. Another Vrt tracks will be added to it. 
+      if(      (*WrkVrtSet)[V1].selTrk.size() <  (*WrkVrtSet)[V2].selTrk.size() )
+                                                                           {int itmp=V2; V2=V1; V1=itmp;}   //Vertex with NTrk=max is chosen
+      else if( (*WrkVrtSet)[V1].selTrk.size() == (*WrkVrtSet)[V2].selTrk.size() )
+         { if( (*WrkVrtSet)[V1].chi2           > (*WrkVrtSet)[V2].chi2 )   {int itmp=V2; V2=V1; V1=itmp;} } // Vertex with minimal Chi2 is chosen
+      //- Fill base track list for new vertex
+      newvrt.selTrk.resize( (*WrkVrtSet)[V1].selTrk.size() );
+      std::copy((*WrkVrtSet)[V1].selTrk.begin(),(*WrkVrtSet)[V1].selTrk.end(), newvrt.selTrk.begin());
+      //- Identify non-common tracks in second vertex
+      std::vector<int> noncommonTrk(0);
+      for(auto &it : (*WrkVrtSet)[V2].selTrk){
+        if( std::find((*WrkVrtSet)[V1].selTrk.begin(), (*WrkVrtSet)[V1].selTrk.end(), it) == (*WrkVrtSet)[V1].selTrk.end() )
+           noncommonTrk.push_back(it);
+      }
+      //      
+      // Try to add non-common tracks one by one
+      std::vector<const xAOD::TrackParticle*>  fitTrackList(0);
+      std::vector<int> detachedTrk(0);
+      StatusCode sc; sc.setChecked();
+      WrkVrt bestVrt;
+      bool foundMerged=false;
+      for( auto nct : noncommonTrk){  
+         fitTrackList.clear();
+         for(int it=0; it<(int)newvrt.selTrk.size(); it++)fitTrackList.push_back( AllTrackList[newvrt.selTrk[it]] );
+         fitTrackList.push_back( AllTrackList.at(nct) );
+         m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V1].vertex[0],(*WrkVrtSet)[V1].vertex[1],(*WrkVrtSet)[V1].vertex[2],istate);
+         sc=m_fitSvc->VKalVrtFit(fitTrackList, neutralPartDummy, newvrt.vertex, newvrt.vertexMom, newvrt.vertexCharge, newvrt.vertexCov,
+                                 newvrt.chi2PerTrk, newvrt.trkAtVrt, newvrt.chi2,
+                                 istate, false);
+         if( sc.isFailure() || TMath::Prob( newvrt.chi2, 2*newvrt.selTrk.size()+2-3)<m_globVrtProbCut ) {
+           detachedTrk.push_back(nct);
+           continue;
+         }
+         newvrt.selTrk.push_back(nct);   // Compatible track. Add to common vertex.
+         bestVrt=newvrt;
+         foundMerged=true;
+      }
+      if(foundMerged)(*WrkVrtSet)[V1]=bestVrt;
+      (*WrkVrtSet)[V2].Good=false;
+      //
+      // Now detached tracks
+      if(detachedTrk.size()>1){
+         WrkVrt nVrt;
+         fitTrackList.clear(); nVrt.selTrk.clear();
+         for(auto nct : detachedTrk){ fitTrackList.push_back( AllTrackList[nct] );  nVrt.selTrk.push_back(nct); }
+         m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V2].vertex[0],(*WrkVrtSet)[V2].vertex[1],(*WrkVrtSet)[V2].vertex[2],istate);
+         sc=m_fitSvc->VKalVrtFit(fitTrackList, neutralPartDummy, nVrt.vertex, nVrt.vertexMom, nVrt.vertexCharge, nVrt.vertexCov,
+                                 nVrt.chi2PerTrk, nVrt.trkAtVrt, nVrt.chi2,
+                                 istate, false);
+         if(sc.isSuccess()) (*WrkVrtSet).push_back(nVrt);
+      } else if( detachedTrk.size()==1 ){
+         bool tFound=false;
+         for( auto &vrt : (*WrkVrtSet) ){  
+           if( !vrt.Good || vrt.selTrk.size()<2 )continue;
+           if( std::find(vrt.selTrk.begin(), vrt.selTrk.end(), detachedTrk[0]) != vrt.selTrk.end() ) { tFound=true; break; }
+         }
+         if( !tFound ) {   //Track is not present in other vertices. 
+           double Chi2min=1.e9; int selectedTrk=-1;
+           WrkVrt saveVrt;
+           fitTrackList.resize(2);
+           fitTrackList[0]= AllTrackList[detachedTrk[0]];
+           for(auto trk : (*WrkVrtSet)[V2].selTrk){
+              if(trk==detachedTrk[0])continue;
+              WrkVrt nVrt; nVrt.Good=true;
+              fitTrackList[1]=AllTrackList[trk];
+              m_fitSvc->setApproximateVertex( (*WrkVrtSet)[V2].vertex[0],(*WrkVrtSet)[V2].vertex[1],(*WrkVrtSet)[V2].vertex[2],istate);
+              sc=m_fitSvc->VKalVrtFit(fitTrackList, neutralPartDummy, nVrt.vertex, nVrt.vertexMom, nVrt.vertexCharge, nVrt.vertexCov,
+                                      nVrt.chi2PerTrk, nVrt.trkAtVrt, nVrt.chi2,
+                                      istate, false);
+              if(sc.isSuccess() &&   nVrt.chi2<Chi2min) {Chi2min=nVrt.chi2;  saveVrt=nVrt; selectedTrk=trk; }
+           }    
+	   if(Chi2min<1.e9){
+             saveVrt.selTrk.resize(1); saveVrt.selTrk[0]=detachedTrk[0];
+             saveVrt.detachedTrack=selectedTrk;
+             saveVrt.vertexMom=MomAtVrt(saveVrt.trkAtVrt[0]);  //redefine vertex momentum
+             (*WrkVrtSet).push_back(saveVrt);
+           }
+         }
+      }
+      return ;
+   }
+
+//
+//  Iterate track removal until vertex get good Chi2
+//
+
+   double  NewVrtSecInclusiveTool::improveVertexChi2( std::vector<WrkVrt> *WrkVrtSet, int V, std::vector<const xAOD::TrackParticle*> & AllTrackList,
+                                                    Trk::IVKalState& istate,
+                                                    bool ifCovV0)
+   const
+   {
+
+      int NTrk=(*WrkVrtSet)[V].selTrk.size();
+      if( NTrk<2 )return 0.;
+      double Prob=TMath::Prob( (*WrkVrtSet)[V].chi2, 2*NTrk-3);
+      //
+      //----Start track removal iterations
+      while(Prob<0.01){
+        NTrk=(*WrkVrtSet)[V].selTrk.size();
+        if(NTrk==2)return Prob;
+        int SelT=-1; double Chi2Max=0.;
+        for(int i=0; i<NTrk; i++){
+          if( (*WrkVrtSet)[V].chi2PerTrk[i]>Chi2Max) { 
+            Chi2Max=(*WrkVrtSet)[V].chi2PerTrk[i];  
+            SelT=i;
+          }
+        }
+        if (SelT<0) return 0; 
+        (*WrkVrtSet)[V].detachedTrack=(*WrkVrtSet)[V].selTrk[SelT];
+        (*WrkVrtSet)[V].selTrk.erase( (*WrkVrtSet)[V].selTrk.begin() + SelT ); //remove track
+        StatusCode sc = refitVertex( WrkVrtSet, V, AllTrackList, istate, ifCovV0);
+        if(sc.isFailure())return 0.;
+        Prob=TMath::Prob( (*WrkVrtSet)[V].chi2, 2*(NTrk-1)-3);
+      }
+      return Prob;
+   }
+
+
+
+
+   StatusCode NewVrtSecInclusiveTool::refitVertex( std::vector<WrkVrt> *WrkVrtSet,
+                                                 int SelectedVertex,
+                                                 std::vector<const xAOD::TrackParticle*> & selectedTracks,
+                                                 Trk::IVKalState& istate,
+                                                 bool ifCovV0) const
+   {
+      int nth = (*WrkVrtSet)[SelectedVertex].selTrk.size();
+ 
+      if(nth<2) return StatusCode::SUCCESS;
+ 
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      std::vector<const xAOD::TrackParticle*>  ListTracks(0);
+      for(int i=0;i<nth;i++) {
+	  int j=(*WrkVrtSet)[SelectedVertex].selTrk[i];                           /*Track number*/
+          ListTracks.push_back( selectedTracks[j] );
+      }
+      (*WrkVrtSet)[SelectedVertex].Good = false;
+      (*WrkVrtSet)[SelectedVertex].chi2PerTrk.resize(nth);
+      for(int i=0;i<nth;i++)(*WrkVrtSet)[SelectedVertex].chi2PerTrk[i]=100000.+i; //VK safety
+
+      m_fitSvc->setApproximateVertex((*WrkVrtSet)[SelectedVertex].vertex[0],
+	                             (*WrkVrtSet)[SelectedVertex].vertex[1],
+	                             (*WrkVrtSet)[SelectedVertex].vertex[2],
+                                     istate);
+      StatusCode sc=m_fitSvc->VKalVrtFit(ListTracks, neutralPartDummy,
+                                (*WrkVrtSet)[SelectedVertex].vertex,
+                                (*WrkVrtSet)[SelectedVertex].vertexMom,
+				(*WrkVrtSet)[SelectedVertex].vertexCharge,
+		                (*WrkVrtSet)[SelectedVertex].vertexCov,
+				(*WrkVrtSet)[SelectedVertex].chi2PerTrk, 
+				(*WrkVrtSet)[SelectedVertex].trkAtVrt,
+				(*WrkVrtSet)[SelectedVertex].chi2,
+                                 istate, ifCovV0);
+      if(sc.isSuccess())(*WrkVrtSet)[SelectedVertex].Good = true;
+      if((*WrkVrtSet)[SelectedVertex].chi2PerTrk.size()==2) 
+         (*WrkVrtSet)[SelectedVertex].chi2PerTrk[0]=
+	 (*WrkVrtSet)[SelectedVertex].chi2PerTrk[1]=(*WrkVrtSet)[SelectedVertex].chi2/2.;
+      return sc;
+   }
+
+
+
+   double NewVrtSecInclusiveTool::refitVertex(WrkVrt &Vrt,
+                                            std::vector<const xAOD::TrackParticle*> & selectedTracks,
+                                            Trk::IVKalState& istate,
+                                            bool ifCovV0) const
+   {
+      int i,j;
+      int nth = Vrt.selTrk.size();
+ 
+      if(nth<2) return -1.;
+ 
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      std::vector<const xAOD::TrackParticle*>  ListTracks(0);
+      for(i=0;i<nth;i++) {
+	  j=Vrt.selTrk[i];                           /*Track number*/
+          ListTracks.push_back( selectedTracks[j] );
+      }
+      Vrt.Good = false;
+      Vrt.chi2PerTrk.resize(nth);
+      for(i=0;i<nth;i++)Vrt.chi2PerTrk[i]=100000.+i; //VK safety
+
+      m_fitSvc->setApproximateVertex(Vrt.vertex[0],Vrt.vertex[1],Vrt.vertex[2],istate);
+      StatusCode sc=m_fitSvc->VKalVrtFit(ListTracks,neutralPartDummy,Vrt.vertex,Vrt.vertexMom,Vrt.vertexCharge,
+                                         Vrt.vertexCov,Vrt.chi2PerTrk, Vrt.trkAtVrt,Vrt.chi2,
+                                         istate, ifCovV0);
+      if(sc.isSuccess())Vrt.Good = true;
+      else {Vrt.Good = false; return -1.;}
+      if(Vrt.chi2PerTrk.size()==2) Vrt.chi2PerTrk[0]=Vrt.chi2PerTrk[1]=Vrt.chi2/2.;
+      return TMath::Prob( Vrt.chi2, 2*nth-1);
+   }
+
+
+   bool NewVrtSecInclusiveTool::isPart( std::deque<long int> test, std::deque<long int> base)
+   const
+   {
+      std::deque<long int>::iterator trk=test.begin();
+      for(trk=test.begin(); trk!=test.end(); trk++)
+         if(std::find(base.begin(), base.end(), (*trk)) == base.end()) return false;  //element not found => test is not part of base
+      return true;
+   }
+
+   double NewVrtSecInclusiveTool::MomProjDist(const Amg::Vector3D & SecVrt,const xAOD::Vertex &PrimVrt,const TLorentzVector &Mom)
+   const
+   {
+      Amg::Vector3D vv=SecVrt-PrimVrt.position();
+      return ( vv.x()*Mom.X()+vv.y()*Mom.Y()+vv.z()*Mom.Z() )/ Mom.P();
+   }
+
+} //end namespace
+
+
+
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/NewVrtSecInclusiveTool.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/NewVrtSecInclusiveTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5b18338fc9941b66692c1097857d6e8ade31b29a
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/NewVrtSecInclusiveTool.cxx
@@ -0,0 +1,345 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///  @author  Vadim Kostyukhin <vadim.kostyukhin@cern.ch>
+///
+
+
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+#include "VxSecVertex/VxSecVertexInfo.h"
+#include "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+#include "InDetBeamSpotService/IBeamCondSvc.h"
+#include "PathResolver/PathResolver.h"
+ 
+#include "GaudiKernel/ITHistSvc.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TTree.h"
+#include "TMath.h"
+#include "TFile.h"
+#include "MVAUtils/BDT.h" 
+//
+
+
+namespace Rec {
+
+//
+//Constructor-------------------------------------------------------------- 
+NewVrtSecInclusiveTool::NewVrtSecInclusiveTool(const std::string& type,
+                                           const std::string& name,
+                                           const IInterface* parent):
+    AthAlgTool(type,name,parent),
+    m_cutSctHits(4),
+    m_cutPixelHits(2),
+    m_cutSiHits(8),
+    m_cutBLayHits(0),
+    m_cutSharedHits(1),
+    m_cutPt(500.),
+    m_cutZVrt(15.),
+    m_cutA0(10.),
+    m_cutChi2(5.),
+    m_sel2VrtProbCut(0.02),
+    m_globVrtProbCut(0.005),
+    m_maxSVRadiusCut(140.),
+    m_selVrtSigCut(3.0),
+    m_trkSigCut(2.0),
+    m_a0TrkErrorCut(1.0),
+    m_zTrkErrorCut(5.0),
+    m_VrtMassLimit(5500.),
+    m_Vrt2TrMassLimit(4000.),
+    m_Vrt2TrPtLimit(5.e5),
+    m_antiPileupSigRCut(2.0),
+    m_dRdZRatioCut(0.25),
+    m_v2tIniBDTCut(-0.6),
+    m_v2tFinBDTCut(0.),
+    m_vertexMergeCut(3.),
+    m_trackDetachCut(6.),
+    m_beampipeR(24.3),
+    m_removeTrkMatSignif(0.),
+    m_fillHist(false),
+    m_useVertexCleaning(true),
+    m_multiWithOneTrkVrt(true),
+    m_calibFileName("Fake2TrVertexReject.MVA.v01.root"),
+    m_SV2T_BDT(nullptr),
+    m_beamService("BeamCondSvc",name),
+    m_fitSvc("Trk::TrkVKalVrtFitter/VertexFitterTool",this)
+   {
+//
+// Declare additional interface
+//
+    declareInterface< IVrtInclusive >(this);
+// Properties
+//
+//
+    declareProperty("CutSctHits",    m_cutSctHits ,  "Remove track is it has less SCT hits" );
+    declareProperty("CutPixelHits",  m_cutPixelHits, "Remove track is it has less Pixel hits");
+    declareProperty("CutSiHits",     m_cutSiHits,    "Remove track is it has less Pixel+SCT hits"  );
+    declareProperty("CutBLayHits",   m_cutBLayHits,  "Remove track is it has less B-layer hits"   );
+    declareProperty("CutSharedHits", m_cutSharedHits,"Reject final 2tr vertices if tracks have shared hits" );
+
+    declareProperty("CutPt",         m_cutPt,     "Track Pt selection cut"  );
+    declareProperty("CutA0",         m_cutA0,     "Track A0 selection cut"  );
+    declareProperty("CutZVrt",       m_cutZVrt,   "Track Z impact selection cut");
+    declareProperty("CutChi2",       m_cutChi2,   "Track Chi2 selection cut" );
+    declareProperty("TrkSigCut",     m_trkSigCut, "Track 3D impact significance w/r primary vertex. Should be >=AntiPileupSigRCut" );
+
+    declareProperty("A0TrkErrorCut",  m_a0TrkErrorCut,  "Track A0 error cut" );
+    declareProperty("ZTrkErrorCut",   m_zTrkErrorCut,   "Track Z impact error cut" );
+    declareProperty("VrtMassLimit",   m_VrtMassLimit,   "Maximal allowed mass for found vertices" );
+    declareProperty("Vrt2TrMassLimit",m_Vrt2TrMassLimit,"Maximal allowed mass for 2-track vertices" );
+    declareProperty("Vrt2TrPtLimit",  m_Vrt2TrPtLimit,  "Maximal allowed Pt for 2-track vertices. Calibration limit" );
+
+    declareProperty("Sel2VrtProbCut",    m_sel2VrtProbCut, "Cut on probability of 2-track vertex for initial selection"  );
+    declareProperty("GlobVrtProbCut",    m_globVrtProbCut, "Cut on probability of any vertex for final selection"  );
+    declareProperty("MaxSVRadiusCut",    m_maxSVRadiusCut, "Cut on maximal radius of SV (def = Pixel detector size)"  );
+    declareProperty("SelVrtSigCut",      m_selVrtSigCut,  "Cut on significance of 3D distance between vertex and PV"  );
+    declareProperty("AntiPileupSigRCut", m_antiPileupSigRCut,  "Upper cut on significance of 2D distance between beam and perigee"  );
+    declareProperty("dRdZRatioCut",      m_dRdZRatioCut,  "Cut on dR/dZ ratio to remove pileup tracks"  );
+    declareProperty("v2tIniBDTCut",      m_v2tIniBDTCut,  "Initial BDT cut for 2track vertices selection "  );
+    declareProperty("v2tFinBDTCut",      m_v2tFinBDTCut,  "Final BDT cut for 2track vertices selection "  );
+
+    declareProperty("FillHist",   m_fillHist, "Fill technical histograms"  );
+
+
+    declareProperty("useVertexCleaning",  m_useVertexCleaning,    "Clean vertices by requiring pixel hit presence according to vertex position" );
+
+    declareProperty("MultiWithOneTrkVrt", m_multiWithOneTrkVrt,"Allow one-track-vertex addition to already found secondary vertices");
+
+    declareProperty("VertexMergeCut",	  m_vertexMergeCut, "To allow vertex merging for MultiVertex Finder" );
+    declareProperty("TrackDetachCut",	  m_trackDetachCut, "To allow track from vertex detachment for MultiVertex Finder" );
+
+    declareProperty("beampipeR",	  m_beampipeR, "Radius of the beampipe material" );
+    declareProperty("removeTrkMatSignif", m_removeTrkMatSignif, "Significance of Vertex-TrackingMaterial distance for removal. No removal if <=0." );
+
+    declareProperty("calibFileName", m_calibFileName, " MVA calibration file for 2-track fake vertices removal" );
+
+    declareProperty("BeamSpotSvc",         m_beamService, "Name of the BeamSpot service");
+    declareProperty("VertexFitterTool",    m_fitSvc, "Name of the Vertex Fitter tool");
+//
+    m_massPi  =  Trk::ParticleMasses().mass[Trk::pion];
+    m_massP   =  Trk::ParticleMasses().mass[Trk::proton];
+    m_massE   =  Trk::ParticleMasses().mass[Trk::electron];
+    m_massK0  =  Trk::ParticleMasses().mass[Trk::k0];
+    m_massLam =  1115.683  ;
+    m_compatibilityGraph = nullptr;
+    m_instanceName=name;
+
+   }
+
+//Destructor---------------------------------------------------------------
+    NewVrtSecInclusiveTool::~NewVrtSecInclusiveTool(){
+     ATH_MSG_DEBUG("NewVrtSecInclusiveTool destructor called");
+   }
+
+//Initialize---------------------------------------------------------------
+   StatusCode NewVrtSecInclusiveTool::initialize(){
+     ATH_MSG_DEBUG( "Initialising NewVrtSecInclusiveTool- Package version: " << PACKAGE_VERSION ); 
+     m_compatibilityGraph = new boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS>();
+
+     ATH_CHECK( m_beamService.retrieve() );
+     ATH_CHECK( m_extrapolator.retrieve() );
+
+     ATH_CHECK( m_fitSvc.retrieve() );
+     ATH_MSG_DEBUG("NewVrtSecInclusiveTool TrkVKalVrtFitter found");
+
+//------------------------------------------       
+//
+     ITHistSvc*     hist_root=0;
+     if(m_fillHist){
+
+       StatusCode sc = service( "THistSvc", hist_root); 
+       if( sc.isFailure() )  ATH_MSG_DEBUG("Could not find THistSvc service");
+       else                  ATH_MSG_DEBUG("NewVrtSecInclusiveTool Histograms found");
+ 
+       m_hb_massPiPi   = new TH1D("massPiPi"," mass PiPi",200,0., 4000.);
+       m_hb_massPiPi1  = new TH1D("massPiPi1"," mass PiPi",200,0., 4000.);
+       m_hb_massPPi    = new TH1D("massPPi"," massPPi", 100,1000., 1250.);
+       m_hb_massEE     = new TH1D("massEE"," massEE", 100,0., 200.);
+       m_hb_nvrt2      = new TH1D("nvrt2"," vertices2", 50,0., 50.);
+       m_hb_ratio      = new TH1D("ratio"," ratio", 51,0., 1.02);
+       m_hb_totmass    = new TH1D("totmass"," totmass", 250,0., 10000.);
+       m_hb_impact     = new TH1D("impact", " impact", 100,0., 20.);
+       m_hb_impactR    = new TH1D("impactR"," impactR", 400,-30., 70.);
+       m_hb_impactZ    = new TH1D("impactZ"," impactZ", 100,-30., 70.);
+       m_hb_impactRZ   = new TH2D("impactRZ"," impactRZ", 40,-10., 10., 60, -30.,30. );
+       m_hb_pileupRat  = new TH1D("pileupRatio"," dR/dZ ratio", 100, 0., 1.);
+       m_hb_trkD0      = new TH1D("trkD0"," d0 of tracks", 100, 0., 10.);
+       m_hb_trkZ       = new TH1D("trkZ"," Z of tracks", 120,-60., 60.);
+       m_hb_r2d        = new TH1D("r2interact","Interaction radius 2tr selected", 150,0., 150.);
+       m_hb_ntrksel    = new TH1F("NTrkSel","Number of selected tracks", 200,0., 200.);
+       m_hb_ntrkInput  = new TH1F("NTrkInput","Number of provided tracks", 200,0., 1000.);
+       m_hb_trkSelect  = new TH1F("TrkSelect","Track selection efficiency", 15,0., 15.);
+       m_hb_signif3D   = new TH1D("signif3D"," Signif3D for initial 2tr vertex", 140,-20., 50.);
+       m_hb_sig3DTot   = new TH1D("sig3dcommon"," Signif3D for common vertex", 140,-20., 50.);
+       m_hb_sig3D1tr   = new TH1D("sig3D1tr","Signif3D for 1tr  vertices", 140,-20., 50.);
+       m_hb_sig3D2tr   = new TH1D("sig3D2tr","Signif3D for 2tr single vertex", 140,-20., 50.);
+       m_hb_sig3DNtr   = new TH1D("sig3DNtr","Signif3D for many-tr single vertex", 140,-20., 50.);
+       m_hb_goodvrtN   = new TH1F("goodvrtN","Number of good vertices", 20,0., 20.);
+       m_hb_goodvrt1N  = new TH1F("goodvrt1N","Number of good 1-track vertices", 20,0., 20.);
+       m_hb_distVV     = new TH1D("distvv","Vertex-Vertex dist", 100,0., 20.);
+       m_hb_diffPS     = new TH1D("diffPS","Primary-Secondary assoc", 200,-20., 20.);
+       m_hb_rawVrtN    = new TH1F("rawVrtN","Number of raw vertices multivertex case", 20, 0., 20.);
+       m_hb_cosSVMom   = new TH1F("cosSVMom","SV-PV vs SV momentum ", 100, 0., 1.);
+       m_hb_etaSV      = new TH1F("etaSV"," Eta of SV-PV ", 100, -5., 5.);
+       m_hb_fakeSVBDT  = new TH1F("fakeSVBDT"," BDT for fake SV rejection", 100, -1., 1.);
+//---
+       std::string histDir;
+       histDir="/file1/stat/MultiSVrt"+m_instanceName+"/";
+       sc = hist_root->regHist(histDir+"massPiPi", m_hb_massPiPi);
+       sc = hist_root->regHist(histDir+"massPiPi1", m_hb_massPiPi1);
+       sc = hist_root->regHist(histDir+"massPPi", m_hb_massPPi);
+       sc = hist_root->regHist(histDir+"massEE", m_hb_massEE );
+       sc = hist_root->regHist(histDir+"nvrt2", m_hb_nvrt2);
+       sc = hist_root->regHist(histDir+"ratio", m_hb_ratio);
+       sc = hist_root->regHist(histDir+"totmass", m_hb_totmass);
+       sc = hist_root->regHist(histDir+"impact",    m_hb_impact);
+       sc = hist_root->regHist(histDir+"impactR",   m_hb_impactR);
+       sc = hist_root->regHist(histDir+"impactZ",   m_hb_impactZ);
+       sc = hist_root->regHist(histDir+"impactRZ",  m_hb_impactRZ);
+       sc = hist_root->regHist(histDir+"pileupRatio", m_hb_pileupRat);
+       sc = hist_root->regHist(histDir+"trkD0",     m_hb_trkD0);
+       sc = hist_root->regHist(histDir+"trkZ",      m_hb_trkZ);
+       sc = hist_root->regHist(histDir+"r2interact",m_hb_r2d);
+       sc = hist_root->regHist(histDir+"NTrkSel",   m_hb_ntrksel);
+       sc = hist_root->regHist(histDir+"NTrkInput", m_hb_ntrkInput);
+       sc = hist_root->regHist(histDir+"TrkSelect", m_hb_trkSelect);
+       sc = hist_root->regHist(histDir+"signif3D",  m_hb_signif3D);
+       sc = hist_root->regHist(histDir+"sig3dcommon", m_hb_sig3DTot);
+       sc = hist_root->regHist(histDir+"sig3D1tr",  m_hb_sig3D1tr);
+       sc = hist_root->regHist(histDir+"sig3D2tr",  m_hb_sig3D2tr);
+       sc = hist_root->regHist(histDir+"sig3DNtr",  m_hb_sig3DNtr);
+       sc = hist_root->regHist(histDir+"goodvrtN",  m_hb_goodvrtN);
+       sc = hist_root->regHist(histDir+"goodvrt1N", m_hb_goodvrt1N);
+       sc = hist_root->regHist(histDir+"distVV",    m_hb_distVV);
+       sc = hist_root->regHist(histDir+"diffPS",    m_hb_diffPS);
+       sc = hist_root->regHist(histDir+"rawVrtN",   m_hb_rawVrtN);
+       sc = hist_root->regHist(histDir+"cosSVMom",  m_hb_cosSVMom);
+       sc = hist_root->regHist(histDir+"etaSV",     m_hb_etaSV);
+       sc = hist_root->regHist(histDir+"fakeSVBDT", m_hb_fakeSVBDT);
+       if( sc.isFailure() ) ATH_MSG_INFO( "NewVrtSecInclusive Histogram registration failure!!!");
+       m_w_1 = 1.;
+       //------
+       m_curTup=new DevTuple();
+       m_tuple = new TTree("Vertices","Vertices");
+       std::string TreeDir;
+       TreeDir="/file1/stat/MultiSVrt"+m_instanceName+"/";
+       sc = hist_root->regTree(TreeDir,m_tuple);
+       if (sc.isSuccess()) {
+          m_tuple->Branch("ntrk",       &m_curTup->nTrk,    "ntrk/I");
+          m_tuple->Branch("pttrk",      &m_curTup->pttrk,   "pttrk[ntrk]/F");
+          m_tuple->Branch("Sig3D",      &m_curTup->Sig3D,   "Sig3D[ntrk]/F");
+
+          m_tuple->Branch("n2Vrt",      &m_curTup->n2Vrt,      "n2Vrt/I");
+          m_tuple->Branch("VrtTrkHF",   &m_curTup->VrtTrkHF,   "VrtTrkHF[n2Vrt]/I");
+          m_tuple->Branch("VrtTrkI",    &m_curTup->VrtTrkI,    "VrtTrkI[n2Vrt]/I");
+          m_tuple->Branch("VrtCh",      &m_curTup->VrtCh,      "VrtCh[n2Vrt]/I");
+          m_tuple->Branch("VrtDist2D",  &m_curTup->VrtDist2D,  "VrtDist2D[n2Vrt]/F");
+          m_tuple->Branch("VrtSig3D",   &m_curTup->VrtSig3D,   "VrtSig3D[n2Vrt]/F");
+          m_tuple->Branch("VrtSig2D",   &m_curTup->VrtSig2D,   "VrtSig2D[n2Vrt]/F");
+          m_tuple->Branch("VrtM",       &m_curTup->VrtM,       "VrtM[n2Vrt]/F");
+          m_tuple->Branch("VrtZ",       &m_curTup->VrtZ,       "VrtZ[n2Vrt]/F");
+          m_tuple->Branch("VrtPt",      &m_curTup->VrtPt,      "VrtPt[n2Vrt]/F");
+          m_tuple->Branch("VrtEta",     &m_curTup->VrtEta,     "VrtEta[n2Vrt]/F");
+          m_tuple->Branch("VrtIBL",     &m_curTup->VrtIBL,     "VrtIBL[n2Vrt]/I");
+          m_tuple->Branch("VrtBL",      &m_curTup->VrtBL,      "VrtBL[n2Vrt]/I");
+          m_tuple->Branch("VrtSinSPM",  &m_curTup->VrtSinSPM,  "VrtSinSPM[n2Vrt]/F");
+          m_tuple->Branch("VMinPtT",    &m_curTup->VMinPtT,    "VMinPtT[n2Vrt]/F");
+          m_tuple->Branch("VMinS3DT",   &m_curTup->VMinS3DT,   "VMinS3DT[n2Vrt]/F");
+          m_tuple->Branch("VMaxS3DT",   &m_curTup->VMaxS3DT,   "VMaxS3DT[n2Vrt]/F");
+          m_tuple->Branch("VrtProb",    &m_curTup->VrtProb,    "VrtProb[n2Vrt]/F");
+          m_tuple->Branch("VrtHR1",     &m_curTup->VrtHR1,     "VrtHR1[n2Vrt]/F");
+          m_tuple->Branch("VrtHR2",     &m_curTup->VrtHR2,     "VrtHR2[n2Vrt]/F");
+          m_tuple->Branch("VrtBDT",     &m_curTup->VrtBDT,     "VrtBDT[n2Vrt]/F");
+          m_tuple->Branch("VrtDisk",    &m_curTup->VrtDisk,    "VrtDisk[n2Vrt]/I");
+          m_tuple->Branch("VSigMat",    &m_curTup->VSigMat,    "VSigMat[n2Vrt]/F");
+
+          m_tuple->Branch("nNVrt",       &m_curTup->nNVrt,       "nNVrt/I");
+          m_tuple->Branch("NVrtTrk",     &m_curTup->NVrtTrk,     "NVrtTrk[nNVrt]/I");
+          m_tuple->Branch("NVrtTrkHF",   &m_curTup->NVrtTrkHF,   "NVrtTrkHF[nNVrt]/I");
+          m_tuple->Branch("NVrtTrkI",    &m_curTup->NVrtTrkI,    "NVrtTrkI[nNVrt]/I");
+          m_tuple->Branch("NVrtCh",      &m_curTup->NVrtCh,      "NVrtCh[nNVrt]/I");
+          m_tuple->Branch("NVrtDist2D",  &m_curTup->NVrtDist2D,  "NVrtDist2D[nNVrt]/F");
+          m_tuple->Branch("NVrtSig3D",   &m_curTup->NVrtSig3D,   "NVrtSig3D[nNVrt]/F");
+          m_tuple->Branch("NVrtSig2D",   &m_curTup->NVrtSig2D,   "NVrtSig2D[nNVrt]/F");
+          m_tuple->Branch("NVrtM",       &m_curTup->NVrtM,       "NVrtM[nNVrt]/F");
+          m_tuple->Branch("NVrtPt",      &m_curTup->NVrtPt,      "NVrtPt[nNVrt]/F");
+          m_tuple->Branch("NVrtEta",     &m_curTup->NVrtEta,     "NVrtEta[nNVrt]/F");
+          m_tuple->Branch("NVrtIBL",     &m_curTup->NVrtIBL,     "NVrtIBL[nNVrt]/I");
+          m_tuple->Branch("NVrtBL",      &m_curTup->NVrtBL,      "NVrtBL[nNVrt]/I");
+          m_tuple->Branch("NVrtSinSPM",  &m_curTup->NVrtSinSPM,  "NVrtSinSPM[nNVrt]/F");
+          m_tuple->Branch("NVMinPtT",    &m_curTup->NVMinPtT,    "NVMinPtT[nNVrt]/F");
+          m_tuple->Branch("NVMinS3DT",   &m_curTup->NVMinS3DT,   "NVMinS3DT[nNVrt]/F");
+          m_tuple->Branch("NVrtProb",    &m_curTup->NVrtProb,    "NVrtProb[nNVrt]/F");
+          m_tuple->Branch("NVrtBDT",     &m_curTup->NVrtBDT,     "NVrtBDT[nNVrt]/F");
+       }
+     }
+
+//--------------------------------------------------------
+     //std::string fileName="NewVrtSecInclusiveTool/Fake2TrVertexReject.MVA.v01.root";   ///For local calibration file
+     //std::string rootFilePath = PathResolver::find_file(fileName, "DATAPATH");         ///
+     std::string rootFilePath = PathResolver::find_calib_file("NewVrtSecInclusiveTool/"+m_calibFileName);
+     TFile* rootFile = TFile::Open(rootFilePath.c_str(), "READ");    
+     if (!rootFile) {
+        ATH_MSG_FATAL("Could not retrieve root file: " << m_calibFileName);
+        return StatusCode::FAILURE;
+     }
+     TTree * training = (TTree*)rootFile->Get("BDT");
+     m_SV2T_BDT = std::make_unique<MVAUtils::BDT>(training);
+//--------------------------------------------------------
+     return StatusCode::SUCCESS;
+
+   }
+
+
+
+
+  StatusCode NewVrtSecInclusiveTool::finalize()
+  {
+    if(m_compatibilityGraph)delete m_compatibilityGraph;
+    ATH_MSG_DEBUG("NewVrtSecInclusiveTool finalize()");
+    return StatusCode::SUCCESS; 
+  }
+  
+
+
+
+  std::unique_ptr<Trk::VxSecVertexInfo> NewVrtSecInclusiveTool::findAllVertices (
+           const std::vector<const xAOD::TrackParticle*> & inpTrk,
+           const xAOD::Vertex & primVrt ) const 
+  {
+    std::vector<xAOD::Vertex*> listVrtSec(0);
+
+    if(m_fillHist && m_curTup){  
+      m_curTup->nTrk=0;
+      m_curTup->n2Vrt=0;
+      m_curTup->nNVrt=0;
+    };
+
+    workVectorArrxAOD * tmpVectxAOD=new workVectorArrxAOD();
+    tmpVectxAOD->inpTrk.resize(inpTrk.size());
+    std::copy(inpTrk.begin(),inpTrk.end(), tmpVectxAOD->inpTrk.begin());
+    tmpVectxAOD->beamX=m_beamService->beamPos().x();
+    tmpVectxAOD->beamY=m_beamService->beamPos().y();
+    tmpVectxAOD->beamZ=m_beamService->beamPos().z();
+    tmpVectxAOD->tanBeamTiltX=tan(m_beamService->beamTilt(0));
+    tmpVectxAOD->tanBeamTiltY=tan(m_beamService->beamTilt(1));
+    
+
+    listVrtSec = getVrtSecMulti(tmpVectxAOD,primVrt);
+    delete tmpVectxAOD;
+
+
+
+    std::vector<const xAOD::IParticle*>  iparTrkV0(0); 
+    std::unique_ptr<Trk::VxSecVertexInfo> res = std::make_unique<Trk::VxSecVertexInfo>(Trk::VxSecVertexInfo(listVrtSec));
+
+    if(m_fillHist && m_tuple){  m_tuple->Fill(); };
+
+    m_compatibilityGraph->clear();
+    return res;
+ }
+
+
+}  // end Rec namespace
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Sel2TrkVertices.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Sel2TrkVertices.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..1f9e9b53f9a5e904cfc76b0485dc23978d13e497
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Sel2TrkVertices.cxx
@@ -0,0 +1,215 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///     @author  Vadim Kostyukhin <vadim.kostyukhin@cern.ch>
+///
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+#include "GeoPrimitives/GeoPrimitivesHelpers.h"
+#include  "MVAUtils/BDT.h" 
+//-------------------------------------------------
+// Other stuff
+#include  "AnalysisUtils/AnalysisMisc.h"
+#include  "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+
+#include "TMath.h"
+#include "TH1.h"
+#include "TH2D.h"
+//
+//#include<iostream>
+
+
+namespace Rec{
+
+
+//
+//
+//--------------------------------------------------------
+//   Template routine for 2track secondary vertices selection
+//
+
+    void NewVrtSecInclusiveTool::select2TrVrt(std::vector<const xAOD::TrackParticle*>  & selectedTracks,
+                                  const xAOD::Vertex                 & PrimVrt)
+    const
+    {
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      std::vector<const xAOD::TrackParticle*>  tracksForFit(2,0);
+      std::vector<double> impact,impactError;
+      std::vector<double> inpMass(2,m_massPi);
+      long int      Charge;
+      int i,j;
+      StatusCode sc; sc.setChecked();
+      Vrt2Tr tmpVrt;
+      std::vector<Vrt2Tr> all2TrVrt(0);
+      TLorentzVector PSum2T; 
+      Amg::Vector3D iniVrt(0.,0.,0.);
+ //
+      int NTracks = (int) (selectedTracks.size());
+//
+//  impact parameters with sign calculations
+//
+      std::vector<float> covPV=PrimVrt.covariance(); 
+      double signifR=0.,signifZ=0.;
+      std::vector<int> hitIBL(NTracks,0), hitBL(NTracks,0);
+      std::vector<double> trackSignif(NTracks),dRdZratio(NTracks);
+      for (i=0; i<NTracks; i++) {
+         m_fitSvc->VKalGetImpact(selectedTracks[i], PrimVrt.position(), 1, impact, impactError);
+	 signifR = impact[0]/ sqrt(impactError[0]);
+	 signifZ = impact[1]/ sqrt(impactError[2]);
+  	 trackSignif[i] = sqrt( signifR*signifR + signifZ*signifZ);
+	 dRdZratio[i] = fabs(signifR/signifZ);
+         if(m_fillHist){
+	    m_hb_impactR->Fill( signifR, m_w_1); 
+            m_hb_impactZ->Fill( signifZ, m_w_1); 
+            m_hb_impactRZ->Fill(signifR, signifZ, m_w_1); 
+	    m_hb_impact->Fill( trackSignif[i], m_w_1);
+	    if(trackSignif[i]>2.) m_hb_pileupRat->Fill(dRdZratio[i],1.);
+            if( i<DevTuple::maxNTrk && m_curTup){
+	       m_curTup->pttrk[i]=selectedTracks[i]->pt();
+	       m_curTup->Sig3D[i]=trackSignif[i];
+	    }
+	 }
+      }
+
+      if( m_fillHist && m_curTup ){
+          m_curTup->nTrk=std::min(NTracks,DevTuple::maxNTrk);
+          m_curTup->n2Vrt=0;
+      }
+
+      for (i=0; i<NTracks-1; i++) {
+         if(trackSignif[i]<m_trkSigCut || dRdZratio[i]<m_dRdZRatioCut )continue;
+         for (j=i+1; j<NTracks; j++) {
+             if(trackSignif[j]<m_trkSigCut || dRdZratio[j]<m_dRdZRatioCut )continue;
+             PSum2T=selectedTracks[i]->p4()+selectedTracks[j]->p4();
+             if(PSum2T.M()>m_Vrt2TrMassLimit)continue;
+             
+             std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
+             m_fitSvc->setMassInputParticles( inpMass, *state );     // Use pion masses for fit
+             tracksForFit[0]=selectedTracks[i];
+             tracksForFit[1]=selectedTracks[j];
+             sc=m_fitSvc->VKalVrtFitFast(tracksForFit,tmpVrt.fitVertex,*state);            /* Fast crude estimation*/
+
+             if( sc.isFailure()  ) {   /* No initial estimation */ 
+                iniVrt=PrimVrt.position();
+ 	     } else {
+                double PMomVrtDir = ProjSV_PV(tmpVrt.fitVertex,PrimVrt,PSum2T);
+                if( PMomVrtDir>0. ) iniVrt=tmpVrt.fitVertex;                /* Good initial estimation */ 
+                else                iniVrt=PrimVrt.position();
+             }
+             m_fitSvc->setApproximateVertex(iniVrt.x(), iniVrt.y(), iniVrt.z(),*state);
+             sc=m_fitSvc->VKalVrtFit(tracksForFit, neutralPartDummy, tmpVrt.fitVertex, tmpVrt.momentum, Charge,
+                                  tmpVrt.errorMatrix, tmpVrt.chi2PerTrk, tmpVrt.trkAtVrt, tmpVrt.chi2, *state, true );
+             if(sc.isFailure())                       continue;          /* No fit */ 
+             double Prob2v=TMath::Prob(tmpVrt.chi2,1);
+             if( Prob2v < m_sel2VrtProbCut )    continue;
+	     if( tmpVrt.momentum.M()> m_Vrt2TrMassLimit )      continue; 
+  	     if( ProjSV_PV(tmpVrt.fitVertex, PrimVrt, tmpVrt.momentum) < 0.) continue;  // SV-PV don't coincide with summary momentum direction
+             if( tmpVrt.fitVertex.perp() > m_maxSVRadiusCut) continue;                  // Too far from interaction point
+             double cosSVPV=ProjSV_PV(tmpVrt.fitVertex, PrimVrt, tmpVrt.momentum);
+	     TLorentzVector SVPV(tmpVrt.fitVertex.x()-PrimVrt.x(),
+	                         tmpVrt.fitVertex.y()-PrimVrt.y(),
+	                         tmpVrt.fitVertex.z()-PrimVrt.z(), 10.);
+             if(m_fillHist){
+               if(Charge==0){m_hb_massPiPi->Fill(tmpVrt.momentum.M(),1.);}
+               m_hb_cosSVMom->Fill(cosSVPV,1.);
+               m_hb_etaSV->Fill(SVPV.Eta(),1.);
+             }
+	     if(cosSVPV<0.8)continue;
+	     if(tmpVrt.momentum.Pt()<1000.)continue;
+	     float vrtR=tmpVrt.fitVertex.perp();
+//Check close material layer
+             double dstMatSignif=1.e4;
+	     if(m_removeTrkMatSignif>0. && vrtR>20.){
+		if(vrtR<30.){ dstMatSignif=fabs(vrtR-m_beampipeR)/VrtRadiusError(tmpVrt.fitVertex,tmpVrt.errorMatrix );} //beampipe
+		else        { dstMatSignif=distToMatLayerSignificance(tmpVrt);}     //Material in Pixel volume
+		if(dstMatSignif<m_removeTrkMatSignif)continue;
+	     }
+//
+// Check pixel hits vs vertex positions.
+             int ihitIBL  = getIBLHit(selectedTracks[i]);
+	     int jhitIBL  = getIBLHit(selectedTracks[j]);
+             if( ihitIBL<0 && jhitIBL<0)continue;
+             float ihitR  = selectedTracks[i]->radiusOfFirstHit();
+	     float jhitR  = selectedTracks[j]->radiusOfFirstHit();
+             if(m_useVertexCleaning){
+               if(fabs(ihitR-jhitR)>15.) continue;
+               if( std::min(ihitR,jhitR)-vrtR > 36.) continue; // Too big dR between vertex and hit in pixel
+							       // Should be another layer in between 
+               if( std::max(ihitR,jhitR)-vrtR <-10.) continue; // Vertex is behind hit in pixel 
+             }
+//
+// Debugging and BDT
+	     double minPtT = std::min(tracksForFit[0]->pt(),tracksForFit[1]->pt());
+	     double Sig3D=0.,Sig2D=0., Dist2D=0.; 
+             if( m_fillHist && m_curTup ){
+                int ihitBL   = getBLHit (selectedTracks[i]);
+	        int jhitBL   = getBLHit (selectedTracks[j]);
+	        int idisk1=0,idisk2=0,idisk3=0,jdisk1=0,jdisk2=0,jdisk3=0;
+                int sumIBLHits =  std::max(ihitIBL,0)+std::max(jhitIBL,0);
+                int sumBLHits  =  std::max(ihitBL, 0)+std::max(jhitBL, 0);
+                getPixelDiscs(selectedTracks[i],idisk1,idisk2,idisk3);
+                getPixelDiscs(selectedTracks[j],jdisk1,jdisk2,jdisk3);
+                VrtVrtDist(PrimVrt, tmpVrt.fitVertex, tmpVrt.errorMatrix, Sig3D);
+                Dist2D=VrtVrtDist2D(PrimVrt, tmpVrt.fitVertex, tmpVrt.errorMatrix, Sig2D);
+                m_hb_signif3D->Fill(Sig3D,1.);
+                m_curTup->VrtTrkHF [m_curTup->n2Vrt] = getIdHF(tracksForFit[0])+ getIdHF(tracksForFit[1]);       
+                m_curTup->VrtTrkI  [m_curTup->n2Vrt] = getG4Inter(tracksForFit[0])+ getG4Inter(tracksForFit[1]);       
+                m_curTup->VrtCh    [m_curTup->n2Vrt] = Charge;
+                m_curTup->VrtProb  [m_curTup->n2Vrt] = Prob2v;          
+                m_curTup->VrtSig3D [m_curTup->n2Vrt] = Sig3D;
+                m_curTup->VrtSig2D [m_curTup->n2Vrt] = Sig2D;
+                m_curTup->VrtDist2D[m_curTup->n2Vrt] = vrtR<20. ? Dist2D : vrtR;
+                m_curTup->VrtM     [m_curTup->n2Vrt] = tmpVrt.momentum.M();
+                m_curTup->VrtZ     [m_curTup->n2Vrt] = tmpVrt.fitVertex.z();
+                m_curTup->VrtPt    [m_curTup->n2Vrt] = tmpVrt.momentum.Pt();
+                m_curTup->VrtEta   [m_curTup->n2Vrt] = SVPV.Eta();
+                m_curTup->VrtIBL   [m_curTup->n2Vrt] = sumIBLHits;
+                m_curTup->VrtBL    [m_curTup->n2Vrt] = sumBLHits;
+                m_curTup->VrtSinSPM[m_curTup->n2Vrt] = sqrt(1.-cosSVPV*cosSVPV);
+                m_curTup->VMinPtT  [m_curTup->n2Vrt] = minPtT;
+                m_curTup->VMinS3DT [m_curTup->n2Vrt] = std::min(trackSignif[i],trackSignif[j]);
+                m_curTup->VMaxS3DT [m_curTup->n2Vrt] = std::max(trackSignif[i],trackSignif[j]);
+                m_curTup->VrtBDT   [m_curTup->n2Vrt] = 1.1;
+                m_curTup->VrtHR1   [m_curTup->n2Vrt] = ihitR;
+                m_curTup->VrtHR2   [m_curTup->n2Vrt] = jhitR;
+                m_curTup->VrtDisk  [m_curTup->n2Vrt] = idisk1+10*idisk2+20*idisk3+30*jdisk1+40*jdisk2+50*jdisk3;
+                m_curTup->VSigMat  [m_curTup->n2Vrt] = dstMatSignif;
+                if(m_curTup->n2Vrt<DevTuple::maxNVrt-1)m_curTup->n2Vrt++;
+             }
+//-------------------BDT based rejection
+	     if(tmpVrt.momentum.Pt() > m_Vrt2TrPtLimit) continue;
+             VrtVrtDist(PrimVrt, tmpVrt.fitVertex, tmpVrt.errorMatrix, Sig3D);
+	     Dist2D=VrtVrtDist2D(PrimVrt, tmpVrt.fitVertex, tmpVrt.errorMatrix, Sig2D);
+             std::vector<float> VARS(10);
+	     VARS[0]=Prob2v;
+	     VARS[1]=log(tmpVrt.momentum.Pt());
+	     VARS[2]=log(std::max(minPtT,m_cutPt));
+	     VARS[3]=log(vrtR<20. ? Dist2D : vrtR);
+	     VARS[4]=log(std::max(std::min(trackSignif[i],trackSignif[j]),m_trkSigCut));
+	     VARS[5]=log(std::max(trackSignif[i],trackSignif[j]));
+	     VARS[6]=tmpVrt.momentum.M();
+	     VARS[7]=sqrt(fabs(1.-cosSVPV*cosSVPV));
+	     VARS[8]=SVPV.Eta();
+	     VARS[9]=std::max(ihitR,jhitR);
+	     //VARS[9]=sumIBLHits;
+	     //VARS[10]=sumBLHits;
+	     //VARS[11]=std::max(Sig3D,m_selVrtSigCut);
+             float wgtSelect=m_SV2T_BDT->GetGradBoostMVA(VARS);
+             //std::vector<float> weights=m_SV2T_BDT->GetMultiResponse(VARS,3);
+	     //float wgtSelect=weights[0];
+	     if( m_fillHist && m_curTup ) m_curTup->VrtBDT[m_curTup->n2Vrt-1] = wgtSelect;
+	     if(wgtSelect<m_v2tIniBDTCut) continue;
+             //if(weights[2]>weights[0] && weights[2]>weights[1])continue;
+//
+//---  Save good candidate for multi-vertex fit
+//
+             add_edge(i,j,*m_compatibilityGraph);
+         }
+      } 
+
+      return;
+   }
+
+
+}  //end of namespace
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Utilities.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Utilities.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..9377d1a92fb868ac24e8a363d891d905cd168be8
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/Utilities.cxx
@@ -0,0 +1,388 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///    @author Vadim Kostyukhin <vadim.kostyukhin@cern.ch>
+///
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+#include "TrkTrackSummary/TrackSummary.h"
+#include  "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+//-------------------------------------------------
+#include "TrkGeometry/TrackingGeometry.h"
+#include "TrkGeometry/TrackingVolume.h"
+#include "TrkGeometry/Layer.h"
+ // Other stuff
+#include <cmath>
+
+
+namespace Rec{  
+
+
+//  void NewVrtSecInclusiveTool::printWrkSet(const std::vector<WrkVrt> *, const & std::string ) const {
+  void NewVrtSecInclusiveTool::printWrkSet(const std::vector<WrkVrt> *WrkVrtSet, const std::string &name) const {
+    int nGoodV=0;
+    for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) {
+      std::cout<<name
+      <<"= "<<(*WrkVrtSet)[iv].vertex[0]
+      <<", "<<(*WrkVrtSet)[iv].vertex[1]
+      <<", "<<(*WrkVrtSet)[iv].vertex[2]
+      <<" NTrk="<<(*WrkVrtSet)[iv].selTrk.size()
+      <<" is good="<<std::boolalpha<<(*WrkVrtSet)[iv].Good<<std::noboolalpha
+      <<"  Chi2="<<(*WrkVrtSet)[iv].chi2
+      <<"  Mass="<<(*WrkVrtSet)[iv].vertexMom.M()
+      <<"  detached="<<(*WrkVrtSet)[iv].detachedTrack
+      <<"  proj.dist="<<(*WrkVrtSet)[iv].projectedVrt
+      <<" trk=";
+      for(int kk=0; kk<(int)(*WrkVrtSet)[iv].selTrk.size(); kk++) {
+                std::cout<<", "<<(*WrkVrtSet)[iv].selTrk[kk];}
+      //for(int kk=0; kk<(int)(*WrkVrtSet)[iv].selTrk.size(); kk++) {
+      //          std::cout<<", "<<MomAtVrt((*WrkVrtSet)[iv].trkAtVrt[kk]).Perp();}
+      std::cout<<'\n';
+      if((*WrkVrtSet)[iv].Good)nGoodV++;
+    }
+    std::cout<<name<<" N="<<nGoodV<<'\n'; 
+  }
+
+               /*  Technicalities */
+  double NewVrtSecInclusiveTool::ProjSV_PV(const Amg::Vector3D & SV, const xAOD::Vertex & PV, const TLorentzVector & Direction) const
+  {  
+     TVector3 SV_PV( SV.x()-PV.x(), SV.y()-PV.y(), SV.z()-PV.z() );
+     return Direction.Vect().Unit()*SV_PV.Unit();
+  }
+
+  
+  double NewVrtSecInclusiveTool::VrtVrtDist(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                                          const std::vector<double> SecVrtErr, double& signif)
+  const
+  {
+    double distx =  PrimVrt.x()- SecVrt.x();
+    double disty =  PrimVrt.y()- SecVrt.y();
+    double distz =  PrimVrt.z()- SecVrt.z();
+
+
+    AmgSymMatrix(3)  PrimCovMtx=PrimVrt.covariancePosition();  //Create
+    PrimCovMtx(0,0) += SecVrtErr[0];
+    PrimCovMtx(0,1) += SecVrtErr[1];
+    PrimCovMtx(1,0) += SecVrtErr[1];
+    PrimCovMtx(1,1) += SecVrtErr[2];
+    PrimCovMtx(0,2) += SecVrtErr[3];
+    PrimCovMtx(2,0) += SecVrtErr[3];
+    PrimCovMtx(1,2) += SecVrtErr[4];
+    PrimCovMtx(2,1) += SecVrtErr[4];
+    PrimCovMtx(2,2) += SecVrtErr[5];
+
+    AmgSymMatrix(3)  WgtMtx = PrimCovMtx.inverse();
+
+    signif = distx*WgtMtx(0,0)*distx
+            +disty*WgtMtx(1,1)*disty
+            +distz*WgtMtx(2,2)*distz
+         +2.*distx*WgtMtx(0,1)*disty
+         +2.*distx*WgtMtx(0,2)*distz
+         +2.*disty*WgtMtx(1,2)*distz;
+    signif=sqrt(fabs(signif));
+    if( signif!=signif ) signif = 0.;
+    return sqrt(distx*distx+disty*disty+distz*distz);
+  }
+
+  double NewVrtSecInclusiveTool::VrtVrtDist2D(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                                          const std::vector<double> SecVrtErr, double& signif)
+  const
+  {
+    double distx =  PrimVrt.x()- SecVrt.x();
+    double disty =  PrimVrt.y()- SecVrt.y();
+
+
+    AmgSymMatrix(3)  PrimCovMtx=PrimVrt.covariancePosition();  //Create
+    AmgSymMatrix(2)  CovMtx;
+    CovMtx(0,0) = PrimCovMtx(0,0) + SecVrtErr[0];
+    CovMtx(0,1) = PrimCovMtx(0,1) + SecVrtErr[1];
+    CovMtx(1,0) = PrimCovMtx(1,0) + SecVrtErr[1];
+    CovMtx(1,1) = PrimCovMtx(1,1) + SecVrtErr[2];
+
+    AmgSymMatrix(2)  WgtMtx = CovMtx.inverse();
+
+    signif = distx*WgtMtx(0,0)*distx
+            +disty*WgtMtx(1,1)*disty
+         +2.*distx*WgtMtx(0,1)*disty;
+    signif=sqrt(fabs(signif));
+    if( signif!=signif ) signif = 0.;
+    return sqrt(distx*distx+disty*disty);
+  }
+
+
+  double NewVrtSecInclusiveTool::VrtVrtDist(const Amg::Vector3D & Vrt1, const std::vector<double>  & VrtErr1,
+                                            const Amg::Vector3D & Vrt2, const std::vector<double>  & VrtErr2)
+  const
+  {
+    double distx =  Vrt1.x()- Vrt2.x();
+    double disty =  Vrt1.y()- Vrt2.y();
+    double distz =  Vrt1.z()- Vrt2.z();
+
+    AmgSymMatrix(3)  PrimCovMtx;  //Create
+    PrimCovMtx(0,0) =                   VrtErr1[0]+VrtErr2[0];
+    PrimCovMtx(0,1) = PrimCovMtx(1,0) = VrtErr1[1]+VrtErr2[1];
+    PrimCovMtx(1,1) =                   VrtErr1[2]+VrtErr2[2];
+    PrimCovMtx(0,2) = PrimCovMtx(2,0) = VrtErr1[3]+VrtErr2[3];
+    PrimCovMtx(1,2) = PrimCovMtx(2,1) = VrtErr1[4]+VrtErr2[4];
+    PrimCovMtx(2,2) =                   VrtErr1[5]+VrtErr2[5];
+
+    AmgSymMatrix(3)  WgtMtx = PrimCovMtx.inverse();
+
+
+    double signif = 
+               distx*WgtMtx(0,0)*distx
+              +disty*WgtMtx(1,1)*disty
+              +distz*WgtMtx(2,2)*distz
+           +2.*distx*WgtMtx(0,1)*disty
+           +2.*distx*WgtMtx(0,2)*distz
+           +2.*disty*WgtMtx(1,2)*distz;
+    signif=sqrt(fabs(signif));
+    if(signif != signif)  signif = 0.;
+    return signif;
+  }
+//
+  double NewVrtSecInclusiveTool::PntPntDist(const Amg::Vector3D & Vrt1, const Amg::Vector3D & Vrt2) const
+  { 
+    double dx =  Vrt1.x()- Vrt2.x();
+    double dy =  Vrt1.y()- Vrt2.y();
+    double dz =  Vrt1.z()- Vrt2.z();
+    return sqrt(dx*dx+dy*dy*dz*dz);
+  }
+//--------------------------------------------------
+// significance along some direction
+//--------------------------------------------------
+double NewVrtSecInclusiveTool::VrtVrtDist(const xAOD::Vertex & PrimVrt, const Amg::Vector3D & SecVrt, 
+                                           const std::vector<double> SecVrtErr, const TLorentzVector & Dir)
+   const
+   {
+     Amg::Vector3D dir(Dir.Vect().Unit().X(), Dir.Vect().Unit().Y(), Dir.Vect().Unit().Z());
+     double projDist=(SecVrt-PrimVrt.position()).dot(dir);
+     double distx =  dir.x()*projDist;
+     double disty =  dir.y()*projDist;
+     double distz =  dir.z()*projDist;
+
+     AmgSymMatrix(3)  PrimCovMtx=PrimVrt.covariancePosition();  //Create
+     PrimCovMtx(0,0) += SecVrtErr[0];
+     PrimCovMtx(0,1) += SecVrtErr[1];
+     PrimCovMtx(1,0) += SecVrtErr[1];
+     PrimCovMtx(1,1) += SecVrtErr[2];
+     PrimCovMtx(0,2) += SecVrtErr[3];
+     PrimCovMtx(2,0) += SecVrtErr[3];
+     PrimCovMtx(1,2) += SecVrtErr[4];
+     PrimCovMtx(2,1) += SecVrtErr[4];
+     PrimCovMtx(2,2) += SecVrtErr[5];
+ 
+     AmgSymMatrix(3)  WgtMtx = PrimCovMtx.inverse();
+ 
+     double signif = distx*WgtMtx(0,0)*distx
+                    +disty*WgtMtx(1,1)*disty
+                    +distz*WgtMtx(2,2)*distz
+                 +2.*distx*WgtMtx(0,1)*disty
+                 +2.*distx*WgtMtx(0,2)*distz
+                 +2.*disty*WgtMtx(1,2)*distz;
+     signif=sqrt(fabs(signif));
+     if( signif!=signif ) signif = 0.;
+     if(projDist<0)signif=-signif;
+     return signif;
+   }
+
+//----------------------------
+//   Vertex error along radius
+//----------------------------
+  double NewVrtSecInclusiveTool::VrtRadiusError(const Amg::Vector3D & SecVrt, const std::vector<double>  & VrtErr) const
+  {
+    double DirX=SecVrt.x(), DirY=SecVrt.y(); 
+    double Covar =    DirX*VrtErr[0]*DirX
+                  +2.*DirX*VrtErr[1]*DirY
+                     +DirY*VrtErr[2]*DirY;
+    Covar /= DirX*DirX + DirY*DirY;
+    Covar=sqrt(fabs(Covar));
+    if(Covar != Covar)  Covar = 0.;
+    return Covar;
+  }
+
+
+    /* Invariant mass calculation for V0 decays*/
+    /* Gives correct mass assignment in case of nonequal masses*/
+
+
+   double NewVrtSecInclusiveTool::massV0(const std::vector< std::vector<double> >& TrkAtVrt,
+                               double massP, double massPi )
+   const
+   {
+        double ap1i=fabs(TrkAtVrt[0][2]); double ap2i=fabs(TrkAtVrt[1][2]);
+        double px = cos(TrkAtVrt[0][0])*sin(TrkAtVrt[0][1])*ap1i 
+                  + cos(TrkAtVrt[1][0])*sin(TrkAtVrt[1][1])*ap2i;
+        double py = sin(TrkAtVrt[0][0])*sin(TrkAtVrt[0][1])*ap1i 
+                  + sin(TrkAtVrt[1][0])*sin(TrkAtVrt[1][1])*ap2i;
+        double pz =                     cos(TrkAtVrt[0][1])*ap1i 
+                  +                     cos(TrkAtVrt[1][1])*ap2i;
+        double ee= (ap1i > ap2i) ? 
+            (sqrt(ap1i*ap1i+massP*massP)+sqrt(ap2i*ap2i+massPi*massPi)):
+            (sqrt(ap2i*ap2i+massP*massP)+sqrt(ap1i*ap1i+massPi*massPi));
+        double test=(ee-pz)*(ee+pz)-px*px-py*py;
+        return test>0 ? sqrt(test) : 0.; 
+    }
+
+
+
+  TLorentzVector NewVrtSecInclusiveTool::MomAtVrt(const std::vector< double >& inpTrk) 
+  const
+  {
+     double api=1./fabs(inpTrk[2]);
+     double px = cos ( inpTrk[0]) * sin(inpTrk[1])*api;
+     double py = sin ( inpTrk[0]) * sin(inpTrk[1])*api;
+     double pz =                    cos(inpTrk[1])*api;
+     double ee = sqrt( px*px + py*py + pz*pz + m_massPi*m_massPi);
+     return TLorentzVector(px,py,pz,ee); 
+   }
+
+
+/*************************************************************************************************************/
+  int   NewVrtSecInclusiveTool::getIBLHit(const xAOD::TrackParticle* Part) const
+  {
+        uint8_t IBLhit,IBLexp;
+        if(!Part->summaryValue( IBLexp,  xAOD::expectInnermostPixelLayerHit) )           IBLexp = 0;
+	if( IBLexp==0 ) return -1;
+        if(!Part->summaryValue( IBLhit,  xAOD::numberOfInnermostPixelLayerHits) )        IBLhit = 0;
+        if(IBLhit) return 1;
+	else       return 0;
+  }
+  int   NewVrtSecInclusiveTool::getBLHit(const xAOD::TrackParticle* Part) const
+  {
+        uint8_t BLhit,BLexp;
+        if(!Part->summaryValue( BLexp,  xAOD::expectNextToInnermostPixelLayerHit) )           BLexp = 0;
+	if( BLexp==0 ) return -1;
+        if(!Part->summaryValue( BLhit,  xAOD::numberOfNextToInnermostPixelLayerHits) )        BLhit = 0;
+        if(BLhit) return 1;
+	else      return 0;
+  }
+
+  void   NewVrtSecInclusiveTool::getPixelDiscs(const xAOD::TrackParticle* Part, int &d0Hit, int &d1Hit, int &d2Hit) const
+  {
+        uint32_t HitPattern=Part->hitPattern();
+	d0Hit=0; if( HitPattern&((1<<Trk::pixelEndCap0)) ) d0Hit=1;
+	d1Hit=0; if( HitPattern&((1<<Trk::pixelEndCap1)) ) d1Hit=1;
+	d2Hit=0; if( HitPattern&((1<<Trk::pixelEndCap2)) ) d2Hit=1;
+  }
+/*************************************************************************************************************/
+
+  int NewVrtSecInclusiveTool::getIdHF(const xAOD::TrackParticle* TP ) const {
+      if( TP->isAvailable< ElementLink< xAOD::TruthParticleContainer> >( "truthParticleLink") ) {
+        const ElementLink<xAOD::TruthParticleContainer>& tplink = 
+                               TP->auxdata< ElementLink< xAOD::TruthParticleContainer > >("truthParticleLink");
+        if( !tplink.isValid() ) return 0;
+        if( TP->auxdata< float >( "truthMatchProbability" ) < 0.75 ) return 0;
+        if( (*tplink)->barcode() > 200000) return 0;
+        if( (*tplink)->hasProdVtx()){
+          if( (*tplink)->prodVtx()->nIncomingParticles()==1){
+             int PDGID1=0, PDGID2=0, PDGID3=0;
+	     const xAOD::TruthParticle * parTP1=getPreviousParent(*tplink, PDGID1);
+	     const xAOD::TruthParticle * parTP2=0;
+	     int noBC1=notFromBC(PDGID1);
+             if(noBC1)  parTP2 = getPreviousParent(parTP1, PDGID2);
+	     int noBC2=notFromBC(PDGID2);
+             if(noBC2 && parTP2) getPreviousParent(parTP2, PDGID3);
+	     int noBC3=notFromBC(PDGID3);
+             if(noBC1 && noBC2 && noBC3)return 0;
+             return 1;  //This is a reconstructed track from B/C decays
+      } } }
+      return 0;
+  }
+
+  int NewVrtSecInclusiveTool::notFromBC(int PDGID) const {
+    int noBC=0;
+    if(PDGID<=0)return 1;
+    if(PDGID>600 && PDGID<4000)noBC=1;
+    if(PDGID<400 || PDGID>5600)noBC=1;
+    if(PDGID==513  || PDGID==523  || PDGID==533  || PDGID==543)noBC=1;  //Remove tracks from B* (they are in PV)
+    if(PDGID==5114 || PDGID==5214 || PDGID==5224 || PDGID==5314 || PDGID==5324)noBC=1; //Remove tracks from B_Barions* (they are in PV)
+  //if(PDGID==413  || PDGID==423  || PDGID==433 )continue;  //Keep tracks from D* (they are from B vertex)
+  //if(PDGID==4114 || PDGID==4214 || PDGID==4224 || PDGID==4314 || PDGID==4324)continue;
+    return noBC;
+  }
+  const xAOD::TruthParticle * NewVrtSecInclusiveTool::getPreviousParent(const xAOD::TruthParticle * child, int & ParentPDG) const {
+    ParentPDG=0;
+    if( child->hasProdVtx() ){
+       if( child->prodVtx()->nIncomingParticles()==1 ){
+            ParentPDG = abs((*(child->prodVtx()->incomingParticleLinks())[0])->pdgId());
+            return *(child->prodVtx()->incomingParticleLinks())[0];
+       }
+    }
+    return 0;
+  }
+
+
+  int NewVrtSecInclusiveTool::getG4Inter(const xAOD::TrackParticle* TP ) const {
+      if( TP->isAvailable< ElementLink< xAOD::TruthParticleContainer> >( "truthParticleLink") ) {
+        const ElementLink<xAOD::TruthParticleContainer>& tplink = 
+                               TP->auxdata< ElementLink< xAOD::TruthParticleContainer > >("truthParticleLink");
+        if( tplink.isValid() && (*tplink)->barcode()>200000) return 1;
+      }
+      return 0;
+  }
+  int NewVrtSecInclusiveTool::getMCPileup(const xAOD::TrackParticle* TP ) const {
+      if( TP->isAvailable< ElementLink< xAOD::TruthParticleContainer> >( "truthParticleLink") ) {
+        const ElementLink<xAOD::TruthParticleContainer>& tplink = 
+                               TP->auxdata< ElementLink< xAOD::TruthParticleContainer > >("truthParticleLink");
+        if( !tplink.isValid() ) return 1;
+      } else { return 1; }
+      return 0;
+  }
+
+  double NewVrtSecInclusiveTool::distToMatLayerSignificance(Vrt2Tr & Vrt) const
+  {
+     if(Vrt.fitVertex.perp()<20.) return 1.e9;
+     double normP=1./Vrt.momentum.P();
+     Amg::Vector3D momentumP(Vrt.momentum.Px()*normP,Vrt.momentum.Py()*normP,Vrt.momentum.Pz()*normP);
+     Amg::Vector3D momentumN=-momentumP;
+     
+     const Trk::Layer * someLayer  = 0;
+     const Trk::Layer * nextLayerP = 0;
+     const Trk::Layer * nextLayerN = 0;
+     auto volume = m_extrapolator->trackingGeometry()->lowestTrackingVolume(Vrt.fitVertex);
+     someLayer = volume->associatedLayer(Vrt.fitVertex);
+     auto material =  someLayer->layerMaterialProperties();
+     if(material){
+       nextLayerP=someLayer;
+     } else {
+       nextLayerP = someLayer->nextLayer(Vrt.fitVertex,momentumP);
+       if(nextLayerP){ if(!nextLayerP->layerMaterialProperties())nextLayerP=0; }
+       nextLayerN = someLayer->nextLayer(Vrt.fitVertex,momentumN);
+       if(nextLayerN){ if(!nextLayerN->layerMaterialProperties())nextLayerN=0; }
+     }
+     momentumP *= 1.e5;   //100GeV to have straight trajectory
+     double charge = 1.;
+     const Trk::Perigee pseudoVrtPart(Vrt.fitVertex, momentumP, charge, Vrt.fitVertex);
+
+     const Trk::TrackParameters * extrapParP=0; //along momentum
+     const Trk::TrackParameters * extrapParN=0; //backward
+     if(nextLayerP){ extrapParP = m_extrapolator->extrapolate(pseudoVrtPart,
+                     nextLayerP->surfaceRepresentation(), Trk::anyDirection, false, Trk::nonInteractingMuon) ;}
+     if(nextLayerN){ extrapParN = m_extrapolator->extrapolate(pseudoVrtPart,
+                     nextLayerN->surfaceRepresentation(), Trk::anyDirection, false, Trk::nonInteractingMuon) ;}
+
+     float distanceP=1.e9, distanceN=1.e9;
+     if(extrapParP)distanceP=PntPntDist(extrapParP->position(), Vrt.fitVertex);
+     if(extrapParN)distanceN=PntPntDist(extrapParN->position(), Vrt.fitVertex);
+     if(distanceP==1.e9 && distanceN==1.e9) return 1.e9;
+
+     //std::pair<const Trk::TrackParameters*,const Trk::Layer*> next= 
+     //         m_extrapolator->extrapolateToNextActiveLayer(pseudoVrtPart,Trk::anyDirection,true,Trk::pion) ;
+
+     double signif=1.e9;
+     std::vector<double> pntCovar={1.e-2,0.,1.e-2,0.,0.,4.e-2};
+     if(distanceP<distanceN)signif=VrtVrtDist(Vrt.fitVertex, Vrt.errorMatrix, extrapParP->position(), pntCovar);
+     else                   signif=VrtVrtDist(Vrt.fitVertex, Vrt.errorMatrix, extrapParN->position(), pntCovar);
+     delete extrapParP;
+     delete extrapParN;
+     return signif;
+  }
+
+ 
+
+ 
+
+}  //end namespace
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/VrtSecMulti.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/VrtSecMulti.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..48342e3225eb6ec03c6d5f77817c7469fa764a60
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/VrtSecMulti.cxx
@@ -0,0 +1,645 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+///
+///    @author Vadim Kostyukhin <vadim.kostyukhin@cern.ch>
+///
+//
+// Header include
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+//-------------------------------------------------
+// Other stuff
+#include  "AnalysisUtils/AnalysisMisc.h"
+#include  "GeoPrimitives/GeoPrimitivesHelpers.h"
+#include  "TrkVKalVrtFitter/TrkVKalVrtFitter.h"
+#include  "MVAUtils/BDT.h" 
+
+#include  "boost/graph/bron_kerbosch_all_cliques.hpp"
+#include  "TMath.h"
+#include  "TH1.h"
+
+#include  <algorithm>
+//
+
+
+namespace Rec{
+
+
+   std::vector<xAOD::Vertex*> NewVrtSecInclusiveTool::getVrtSecMulti(  workVectorArrxAOD * xAODwrk,
+                                                                      const xAOD::Vertex & PrimVrt )
+   const
+   {
+
+      const double probVrtMergeLimit=0.01;
+
+      int inpNPart=0; 
+      int i,j;
+      inpNPart=xAODwrk->inpTrk.size();
+      std::vector<const xAOD::NeutralParticle*> neutralPartDummy(0);
+      ATH_MSG_DEBUG( "getVrtSecMulti() called with NPart=" << inpNPart);
+   
+      std::vector<xAOD::Vertex*>  finalVertices(0); 
+
+      if( inpNPart < 2 ) { return finalVertices;}   // 0,1 track => nothing to do!
+   
+   
+      long int NTracks = 0;
+      selGoodTrkParticle( xAODwrk, PrimVrt);
+      NTracks = xAODwrk->listSelTracks.size();
+
+      if( NTracks < 2 ) { return finalVertices;} // 0,1 selected track => nothing to do!
+
+      ATH_MSG_DEBUG( "Number of selected tracks = " <<NTracks);
+      
+      if(m_fillHist){ m_hb_ntrksel->Fill( (double) NTracks, m_w_1); }
+
+//
+//  inpTrk[]           - input track list
+//  listSelTracks[]    - list of good tracks in jet for vertex search
+//------------------------------------------------------------	 
+//                     Initial track list ready
+//                     Find 2track vertices
+//
+
+      select2TrVrt(xAODwrk->listSelTracks, PrimVrt);
+
+//---
+      ATH_MSG_DEBUG(" Defined edges in the graph="<< num_edges(*m_compatibilityGraph));
+
+//
+//  m_Incomp[]           -  main vector of pointers for multivertex search
+//-----------------------------------------------------------------------------------------------------
+//            Secondary track list is ready
+//            Creation of initial vertex set
+//
+
+
+      std::vector<WrkVrt> *WrkVrtSet= new std::vector<WrkVrt>;
+      WrkVrt newvrt; newvrt.Good=true;
+      std::unique_ptr<Trk::IVKalState> state = m_fitSvc->makeState();
+      StatusCode sc; sc.setChecked(); 
+      long int NPTR=0, nth=2; // VK nth=2 to speed up PGRAPH when it's used
+
+
+      std::vector< std::vector<int> > allCliques;
+      bron_kerbosch_all_cliques(*m_compatibilityGraph, clique_visitor(allCliques));
+      for(int cq=0; cq<(int)allCliques.size();cq++){
+          newvrt.selTrk.clear();
+          NPTR=allCliques[cq].size();
+          for(i=0;i<NPTR;i++){ newvrt.selTrk.push_back(allCliques[cq][i]);}
+//==================================================
+          xAODwrk->tmpListTracks.clear();
+	  TLorentzVector vpsum;
+          for(i=0;i<NPTR;i++) {
+             xAODwrk->tmpListTracks.push_back( xAODwrk->listSelTracks.at(newvrt.selTrk[i]) );
+	     vpsum += xAODwrk->listSelTracks.at(newvrt.selTrk[i])->p4();
+          }
+          sc = m_fitSvc->VKalVrtFitFast(xAODwrk->tmpListTracks,newvrt.vertex,*state);            /* Fast crude estimation*/
+
+          if( sc.isFailure()  ) {   /* No initial estimation */ 
+              m_fitSvc->setApproximateVertex(PrimVrt.x(), PrimVrt.y(), PrimVrt.z(),*state); /*Use as starting point*/
+ 	  } else {
+	      Amg::Vector3D vDist=newvrt.vertex-PrimVrt.position();
+              double MomVrtDir = vpsum.Px()*vDist.x() + vpsum.Py()*vDist.y() + vpsum.Pz()*vDist.z();
+              if( MomVrtDir>0. ) {                           /* Good initial estimation */ 
+                  m_fitSvc->setApproximateVertex(newvrt.vertex.x(),newvrt.vertex.y(),newvrt.vertex.z(),*state); /*Use as starting point*/
+	      }else{
+                  m_fitSvc->setApproximateVertex(PrimVrt.x(), PrimVrt.y(), PrimVrt.z(),*state); 
+              }
+          }
+//  std::cout<<"FoundAppVrt="<<newvrt.vertex[0]<<", "<<newvrt.vertex[1]<<", "<<newvrt.vertex[2]<<'\n';
+	  sc = StatusCode::FAILURE;
+          sc=m_fitSvc->VKalVrtFit(xAODwrk->tmpListTracks, neutralPartDummy,
+	                                     newvrt.vertex,     newvrt.vertexMom, newvrt.vertexCharge, newvrt.vertexCov,
+                                             newvrt.chi2PerTrk, newvrt.trkAtVrt,  newvrt.chi2,
+                                             *state, false);
+
+//  std::cout << "Res="<<newvrt.chi2<<", "<<NPTR<<", "<<newvrt.selTrk[0]<<", "<<newvrt.selTrk[1]<<'\n'; 
+          if( sc.isFailure() )           continue;   /* Bad fit - goto next solution */
+          if(NPTR==2 && newvrt.chi2>10.) continue;   /* Bad 2track vertex */
+          if(newvrt.chi2PerTrk.size()==2) newvrt.chi2PerTrk[0]=newvrt.chi2PerTrk[1]=newvrt.chi2/2.;
+          newvrt.Good         = true;
+          newvrt.nCloseVrt    = 0;
+          newvrt.dCloseVrt    = 1000000.;
+          newvrt.projectedVrt=MomProjDist(newvrt.vertex, PrimVrt, newvrt.vertexMom); //3D SV-PV distance
+          WrkVrtSet->push_back(newvrt);
+    } 
+//==================================================================================
+// boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS>::vertex_iterator vertexIt, vertexEnd;
+// boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS>::adjacency_iterator neighbourIt, neighbourEnd;
+// tie(vertexIt, vertexEnd) = vertices(*m_compatibilityGraph);
+// for (; vertexIt != vertexEnd; ++vertexIt) { std::cout << *vertexIt << " is connected with "; 
+//    tie(neighbourIt, neighbourEnd) = adjacent_vertices(*vertexIt, *m_compatibilityGraph); 
+//    for (; neighbourIt != neighbourEnd; ++neighbourIt) std::cout << *neighbourIt << " ";   std::cout << "\n"; }
+//==================================================================================
+//========= Initial cleaning of solutions
+//-Remove worst track from vertices with very bad Chi2
+    bool disassembled=false;
+    int NSoluI=0;
+    do{ 
+      disassembled=false;
+      NSoluI=(*WrkVrtSet).size();
+      for(int iv=0; iv<NSoluI; iv++){
+        if(!(*WrkVrtSet)[iv].Good || (*WrkVrtSet)[iv].selTrk.size() == 2 ) continue;
+        if( TMath::Prob( (*WrkVrtSet)[iv].chi2, 2*(*WrkVrtSet)[iv].selTrk.size()-3) <1.e-3){
+          //printWrkSet(WrkVrtSet,"BigChi2Vertex present");
+          DisassembleVertex(WrkVrtSet,iv,xAODwrk->listSelTracks,*state);
+          disassembled=true;
+      } }
+    }while(disassembled);
+//-Modify too heavy vertices 
+    for(auto & iv : (*WrkVrtSet)){
+      if( iv.vertexMom.M()>m_VrtMassLimit ) {
+        int it_bad=mostHeavyTrk(iv,xAODwrk->listSelTracks);
+        if(it_bad>-1){
+	  iv.selTrk.erase( iv.selTrk.begin() + it_bad );
+	  refitVertex(iv, xAODwrk->listSelTracks, *state, false);
+     } } }
+//-Remove vertices fully contained in other vertices 
+    while( (*WrkVrtSet).size()>1 ){
+      int tmpN=(*WrkVrtSet).size();  int iv=0;
+      for(; iv<tmpN-1; iv++){        int jv=iv+1;
+        if(!(*WrkVrtSet)[iv].Good )               continue;
+        for(; jv<tmpN; jv++){
+          if(!(*WrkVrtSet)[jv].Good )             continue;
+          int nTCom=nTrkCommon( WrkVrtSet, iv, jv);
+          if(      nTCom==(int)(*WrkVrtSet)[iv].selTrk.size()){  (*WrkVrtSet).erase((*WrkVrtSet).begin()+iv); break; }
+          else if( nTCom==(int)(*WrkVrtSet)[jv].selTrk.size()){  (*WrkVrtSet).erase((*WrkVrtSet).begin()+jv); break; }
+        }   if(jv!=tmpN)   break;  // One vertex is erased. Restart check
+      }     if(iv==tmpN-1) break;  // No vertex deleted
+    }
+//
+//- Try to merge all vertices with common tracks
+    std::multimap<int,std::pair<int,int>> vrtWithCommonTrk;
+    std::multimap<int,std::pair<int,int>>::reverse_iterator icvrt;
+    do{
+      NSoluI=(*WrkVrtSet).size();
+      vrtWithCommonTrk.clear();
+      for(int iv=0; iv<NSoluI-1; iv++ ){  for(int jv=iv+1; jv<NSoluI; jv++){
+          if(!(*WrkVrtSet)[iv].Good || !(*WrkVrtSet)[jv].Good)    continue;
+          int nTCom=nTrkCommon( WrkVrtSet, iv, jv);     if(!nTCom)continue;
+          vrtWithCommonTrk.emplace(nTCom,std::make_pair(iv,jv));
+      } }
+      //============================== DEBUG output
+      //printWrkSet(WrkVrtSet,"InitialVrts");
+      //for(auto ku : vrtWithCommonTrk)std::cout<<" nCom="<<ku.first<<" v1="<<ku.second.first<<" v2="<<ku.second.second<<'\n';
+      //===========================================
+      for(icvrt=vrtWithCommonTrk.rbegin(); icvrt!=vrtWithCommonTrk.rend(); icvrt++){ 
+          int nTCom=(*icvrt).first;
+          int iv=(*icvrt).second.first;
+          int jv=(*icvrt).second.second;
+          int nTrkI=(*WrkVrtSet)[iv].selTrk.size();
+          int nTrkJ=(*WrkVrtSet)[jv].selTrk.size();
+	  double probV=-1.;
+          probV=mergeAndRefitVertices( WrkVrtSet, iv, jv, newvrt, xAODwrk->listSelTracks, *state);
+          ////std::cout<<" ntcommon="<<(*icvrt).first<<" prb="<<probV<<" itrk="<<nTrkI<<" jtrk="<<nTrkJ<<'\n';
+          if(newvrt.vertexMom.M()>m_VrtMassLimit) continue; //Do not merge vertices if summary one is too heavy
+	  if(probV<probVrtMergeLimit){
+            if(nTrkI==2 || nTrkJ==2 || nTCom<2) continue;
+            if((nTCom>nTrkI-nTCom || nTCom>nTrkJ-nTCom)){  //2 and more common tracks for NTr>=3 vertices. Merge anyway.
+              mergeAndRefitOverlapVertices( WrkVrtSet, iv, jv, xAODwrk->listSelTracks, *state);
+              break; //Vertex list is changed. Restart merging from scratch.
+            }
+            continue;  //Continue merging loop 
+          }
+          newvrt.Good = true;
+          (*WrkVrtSet).push_back(newvrt);
+	  (*WrkVrtSet)[iv].Good=false;      
+	  (*WrkVrtSet)[jv].Good=false;
+          break;  //Merging successful. Break merging loop and remake list of connected vertices
+       }
+    } while( icvrt != vrtWithCommonTrk.rend() );
+    if(m_fillHist){ int cvgood=0; for(int iv=0; iv<(int)(*WrkVrtSet).size(); iv++) if((*WrkVrtSet)[iv].Good)cvgood++;
+                    m_hb_rawVrtN->Fill( (float)cvgood, m_w_1); }
+//
+//-Remove all bad vertices from the working set    
+    int tmpV=0; while( tmpV<(int)(*WrkVrtSet).size() )if( !(*WrkVrtSet)[tmpV].Good ) { (*WrkVrtSet).erase((*WrkVrtSet).begin()+tmpV);} else {tmpV++;}
+    if((*WrkVrtSet).size()==0){             // No vertices at all
+      delete WrkVrtSet;
+      return finalVertices;
+    }
+    //------
+    //printWrkSet(WrkVrtSet,"Interm");
+    //------
+    for( auto &tmpV : (*WrkVrtSet) ) tmpV.projectedVrt=MomProjDist(tmpV.vertex, PrimVrt, tmpV.vertexMom );  //Setup ProjectedVrt
+//----------------------------------------------------------------------------
+//             Here we have the overlapping solutions.
+//             Vertices may have only 1 common track. 
+//              Now solution cleaning
+
+    int nGoodVertices=0;         // Final number of good vertices
+    int n2trVrt=0;               // N of vertices with 2  tracks
+    int nNtrVrt=0;               // N vertices with 3 and more tracks
+    std::vector< std::deque<long int> > *TrkInVrt  =new std::vector< std::deque<long int> >(NTracks);  
+    double foundMaxT; long int SelectedTrack, SelectedVertex;
+    int foundV1, foundV2;
+    
+    trackClassification( WrkVrtSet, TrkInVrt);
+
+    state = m_fitSvc->makeState();
+    while((foundMaxT=maxOfShared( WrkVrtSet, TrkInVrt, SelectedTrack, SelectedVertex))>0) {
+ //std::cout << "MAX="<<foundMaxT<<", "<<SelectedTrack<<", "<<SelectedVertex<<'\n';
+ //std::cout << "VRT="<<minVrtVrtDist( WrkVrtSet, foundV1, foundV2)<<", "<<foundV1<<", "<<foundV2<<'\n';
+ //printWrkSet(WrkVrtSet,"Iterat");
+
+         double foundMinVrtDst = 1000000.;
+         if(foundMaxT<m_trackDetachCut) foundMinVrtDst = minVrtVrtDist( WrkVrtSet, foundV1, foundV2);
+
+//Choice of action
+          if( foundMaxT<m_trackDetachCut && foundMinVrtDst<m_vertexMergeCut && nTrkCommon( WrkVrtSet, foundV1, foundV2)){
+          //if( foundMaxT<m_trackDetachCut && foundMinVrtDst<m_vertexMergeCut){
+             bool vrtMerged=false;   //to check whether something is really merged
+             while(foundMinVrtDst<m_vertexMergeCut){
+               if(foundV1<foundV2) { int tmp=foundV1; foundV1=foundV2; foundV2=tmp;} /*Always drop vertex with smallest number*/
+	       double probV=0.;
+               probV=mergeAndRefitVertices( WrkVrtSet, foundV1, foundV2, newvrt, xAODwrk->listSelTracks, *state);
+	       if(probV>probVrtMergeLimit && newvrt.vertexMom.M()<m_VrtMassLimit){        //  Good merged vertex found
+                 double tstDst=MomProjDist(newvrt.vertex, PrimVrt, newvrt.vertexMom);
+	         if(tstDst>0.){                               // only positive vertex directions are accepted as merging result
+                   std::swap((*WrkVrtSet)[foundV1],newvrt);
+                   (*WrkVrtSet)[foundV1].projectedVrt=tstDst;
+	           (*WrkVrtSet)[foundV2].Good=false;         //Drop vertex
+                   (*WrkVrtSet)[foundV2].selTrk.clear();     //Clean dropped vertex
+	           vrtMerged=true;
+	         }
+               }
+               (*WrkVrtSet)[foundV1].nCloseVrt=-1; (*WrkVrtSet)[foundV1].dCloseVrt=1000000.; //For minVrtVrtDistNext optimisation(!)
+               (*WrkVrtSet)[foundV2].nCloseVrt=-1; (*WrkVrtSet)[foundV2].dCloseVrt=1000000.; //Exclude given pair
+                foundMinVrtDst=minVrtVrtDistNext( WrkVrtSet, foundV1, foundV2);     //Check other vertices
+             }
+	     if(vrtMerged){
+               delete TrkInVrt;
+               TrkInVrt = new std::vector< std::deque<long int> >(NTracks);  
+               trackClassification( WrkVrtSet, TrkInVrt);
+	       continue;  // Something was merged => goto next cycle. Otherwise break the found track-vertex link
+	     }
+	  }
+          removeTrackFromVertex(WrkVrtSet, TrkInVrt, SelectedTrack, SelectedVertex);
+          sc = refitVertex( WrkVrtSet, SelectedVertex, xAODwrk->listSelTracks, *state, false);
+          if( sc.isFailure() ) { (*WrkVrtSet)[SelectedVertex].Good=false;  continue; } //bad vertex
+          (*WrkVrtSet)[SelectedVertex].projectedVrt=MomProjDist((*WrkVrtSet)[SelectedVertex].vertex, PrimVrt, (*WrkVrtSet)[SelectedVertex].vertexMom);
+          if( (*WrkVrtSet)[SelectedVertex].projectedVrt<0. && (*WrkVrtSet)[SelectedVertex].selTrk.size()==2 )
+	      (*WrkVrtSet)[SelectedVertex].Good=false;  // 2track vertex migrates behind PV - drop it.
+          //std::cout<<"Dropped v="<<SelectedVertex<<" dst="<<(*WrkVrtSet)[SelectedVertex].projectedVrt<<'\n';
+    }
+//
+// Final check/merge for close vertices
+//
+    double minDistVV=minVrtVrtDist( WrkVrtSet, foundV1, foundV2); //recalculate VV distances
+    while ( minDistVV < m_vertexMergeCut) {
+        if(foundV1<foundV2) { int tmp=foundV1; foundV1=foundV2; foundV2=tmp;}
+	double probV=0.;
+        probV=mergeAndRefitVertices( WrkVrtSet, foundV1, foundV2, newvrt, xAODwrk->listSelTracks, *state);
+	if(probV>probVrtMergeLimit && newvrt.vertexMom.M()<m_VrtMassLimit){        //  Good merged vertex found
+           double tstDst=MomProjDist(newvrt.vertex, PrimVrt, newvrt.vertexMom);
+	   if(tstDst>0.){                               // only positive vertex directions are accepted as merging result
+              std::swap((*WrkVrtSet)[foundV1],newvrt);
+              (*WrkVrtSet)[foundV1].projectedVrt=tstDst;
+	      (*WrkVrtSet)[foundV2].Good=false;         //Drop vertex
+              (*WrkVrtSet)[foundV2].selTrk.clear();     //Clean dropped vertex
+           }
+        }
+        (*WrkVrtSet)[foundV1].nCloseVrt=-1; (*WrkVrtSet)[foundV1].dCloseVrt=1000000.; //For minVrtVrtDistNext optimisation(!)
+        (*WrkVrtSet)[foundV2].nCloseVrt=-1; (*WrkVrtSet)[foundV2].dCloseVrt=1000000.; //Exclude given pair
+        minDistVV=minVrtVrtDistNext( WrkVrtSet, foundV1, foundV2);
+    }
+//
+// Try to improve vertices with big Chi2 if something went wrong. Just precaution.
+    for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) {
+       if(!(*WrkVrtSet)[iv].Good )                 continue;  //don't work on vertex which is already bad
+       if( (*WrkVrtSet)[iv].selTrk.size()<3 )      continue;
+       double tmpProb=TMath::Prob( (*WrkVrtSet)[iv].chi2, 2*(*WrkVrtSet)[iv].selTrk.size()-3 ); //Chi2 of the original vertex
+       if(tmpProb<m_globVrtProbCut){
+         tmpProb=improveVertexChi2( WrkVrtSet, iv, xAODwrk->listSelTracks, *state, false);
+         if(tmpProb<m_globVrtProbCut)(*WrkVrtSet)[iv].Good=false;
+         (*WrkVrtSet)[iv].projectedVrt=MomProjDist((*WrkVrtSet)[iv].vertex, PrimVrt, (*WrkVrtSet)[iv].vertexMom);
+       }
+    }
+    //
+    //printWrkSet(WrkVrtSet,"Joined");
+//--------------------------------------------------------------------------------------------------------
+// Final vertex selection/cleaning
+//
+    state = m_fitSvc->makeState();
+    double signif3D=0., signif2D=0., vProb=0.;
+    //double Dist3D=0;
+
+//--------- Start with 1-track vertices
+//=First check if the track was detached from a multitrack vertex. If so - reattach. 
+    for(auto &ntrVrt : (*WrkVrtSet)){ if(!ntrVrt.Good || ntrVrt.selTrk.size()<=1)      continue;
+      for(auto &onetVrt : (*WrkVrtSet)){ if(!onetVrt.Good || onetVrt.selTrk.size()!=1) continue;
+        if(ntrVrt.detachedTrack==onetVrt.selTrk[0]){   
+	  WrkVrt newV(ntrVrt); newV.selTrk.push_back(ntrVrt.detachedTrack);
+          vProb = refitVertex( newV, xAODwrk->listSelTracks, *state, true);
+	  if( vProb>probVrtMergeLimit && newV.vertexMom.M()<m_VrtMassLimit ){ onetVrt.Good=false; ntrVrt=newV;  ntrVrt.detachedTrack=-1;}
+	  break;
+    } } }
+//=Recheck if the track was detached from a 2track vertex. If so - reattach. 
+    for(auto &iVrt : (*WrkVrtSet)){   if(!iVrt.Good || iVrt.selTrk.size()!=1) continue;
+      for(auto &jVrt : (*WrkVrtSet)){ if(!jVrt.Good || jVrt.selTrk.size()!=1) continue;
+        if(iVrt.detachedTrack==jVrt.selTrk[0]){   
+	  WrkVrt newV(iVrt); newV.selTrk.push_back(iVrt.detachedTrack);
+          vProb = refitVertex( newV, xAODwrk->listSelTracks, *state, true);
+	  if( vProb>probVrtMergeLimit && newV.vertexMom.M()<m_VrtMassLimit ){ jVrt.Good=false; iVrt=newV;  iVrt.detachedTrack=-1;}
+	  break;
+    } } }
+    for(auto &ntrVrt : (*WrkVrtSet)){ if(!ntrVrt.Good  || ntrVrt.selTrk.size()<=1)  continue;
+      for(auto tr : ntrVrt.selTrk){ 
+        for(auto &onetVrt  : (*WrkVrtSet)){ if(!onetVrt.Good || onetVrt.selTrk.size()!=1) continue;
+	  if(onetVrt.detachedTrack==tr){
+	    WrkVrt newV(ntrVrt); newV.selTrk.push_back(onetVrt.selTrk[0]);
+            vProb = refitVertex( newV, xAODwrk->listSelTracks, *state, true);
+	    if( vProb>probVrtMergeLimit && newV.vertexMom.M()<m_VrtMassLimit ){ onetVrt.Good=false; ntrVrt=newV;}
+    } } } }
+    for(auto & curVrt : (*WrkVrtSet) ) {
+       if(!curVrt.Good )                 continue;  //don't work on vertex which is already bad
+       if(curVrt.selTrk.size() != 1)     continue;
+       curVrt.Good=false;       // Make them bad by default
+       if(m_multiWithOneTrkVrt){          /* 1track vertices left unassigned from good 2tr vertices */
+          VrtVrtDist(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif3D); //VK non-projected signif3D is worse
+          double tmpProb=TMath::Prob( curVrt.chi2, 1);                 //Chi2 of the original 2tr vertex
+          if(tmpProb>0.01){  /* accept only good tracks coming from good 2tr vertex*/
+             std::vector<double> impact,impactError;   double signif3DP = 0;
+             signif3DP=m_fitSvc->VKalGetImpact(xAODwrk->listSelTracks[curVrt.selTrk[0]],PrimVrt.position(), 1, impact, impactError, *state);
+             if(m_fillHist){
+               m_hb_diffPS->Fill( signif3DP, m_w_1); 
+               m_hb_sig3D1tr->Fill( signif3D, m_w_1);
+             }
+             if( signif3DP>2.*m_trkSigCut && signif3D>m_selVrtSigCut) curVrt.Good=true; // accept only tracks which are far from PV
+          }
+       }
+    }
+//-----  Vertices with >1 tracks
+    for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) {
+          WrkVrt & curVrt=(*WrkVrtSet)[iv];
+          if(!curVrt.Good )                      continue;  //don't work on vertex which is already bad
+          nth=(*WrkVrtSet)[iv].selTrk.size(); if(nth == 1) continue;  // 1track vertices are treated already
+          VrtVrtDist(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif3D); 
+          xAODwrk->tmpListTracks.resize(nth);
+          for(i=0;i<nth;i++) {
+            xAODwrk->tmpListTracks[i]=xAODwrk->listSelTracks[curVrt.selTrk[i]];
+          }
+          (*WrkVrtSet)[iv].Good = false;                                     /* Make all vertices bad for futher selection */
+          if(nth <= 1)                          continue;                    /* Definitely bad vertices */
+          if((*WrkVrtSet)[iv].projectedVrt<0.)  continue;                    /* Remove vertices behind primary one */ 
+          if( TMath::Prob( curVrt.chi2, 2*nth-3)<m_globVrtProbCut) continue;           /* Bad Chi2 of refitted vertex  */
+//-----------------------------------------------------------------------------------------
+          if(m_fillHist){ 
+             if(nth==2 && curVrt.vertexCharge==0) m_hb_massPiPi1->Fill(curVrt.vertexMom.M(), m_w_1);
+ 	     m_hb_sig3DTot->Fill( signif3D, m_w_1);
+             if(nth==2)m_hb_sig3D2tr->Fill( signif3D, m_w_1);
+             if(nth >2)m_hb_sig3DNtr->Fill( signif3D, m_w_1);
+          }
+//
+//---  Check V0s and conversions ???
+/*          if(nth==2 && curVrt.vertexCharge==0 && curVrt.detachedTrack<0){
+             double mass_PiPi =  curVrt.vertexMom.M();  
+             double mass_PPi  =  massV0(curVrt.trkAtVrt,m_massP,m_massPi);
+             double mass_EE   =  massV0(curVrt.trkAtVrt,m_massE,m_massE);
+             if(m_fillHist){ m_hb_massPiPi->Fill( mass_PiPi, m_w_1);
+                             m_hb_massPPi ->Fill( mass_PPi,  m_w_1); 
+                             if( curVrt.vertex.perp()>20.)m_hb_massEE  ->Fill( mass_EE,   m_w_1);  } 
+ 	     if( fabs(mass_PiPi-m_massK0) < 22.)     continue;
+ 	     if( fabs(mass_PPi-m_massLam) <  8.)     continue;
+             if( mass_EE < 60. && curVrt.vertex.perp() > 20.) continue;
+          }          
+*/
+//---
+          if(signif3D<m_selVrtSigCut+1.)              continue;      //Main PV-SV distance quality cut 
+          if(curVrt.vertex.perp() > m_maxSVRadiusCut) continue;      // Too far from interaction point
+//---
+          curVrt.Good = true;  /* Vertex is absolutely good */
+    }
+//-------------------------------------------
+// Debug ntuple filling and BDT application
+//
+    std::vector<double> impact,impactError;
+    for(int iv=0; iv<(int)WrkVrtSet->size(); iv++) {
+          WrkVrt & curVrt=(*WrkVrtSet)[iv];
+          nth=curVrt.selTrk.size();
+          if(!curVrt.Good )      continue;  //don't work on vertex which is already bad
+          double minPtT=1.e6, minSig3DT=1.e6, maxSig3DT=0.;
+	  int ntrkBC=0,ntrkI=0,sumIBLHits=0,sumBLHits=0;
+          for(i=0;i<nth;i++) {
+             j=curVrt.selTrk[i];                           /*Track number*/
+             minPtT=std::min( minPtT, xAODwrk->listSelTracks[j]->pt());
+             m_fitSvc->VKalGetImpact(xAODwrk->listSelTracks[j], PrimVrt.position(), 1, impact, impactError);
+	     double SigR2 = impact[0]*impact[0]/impactError[0];
+	     double SigZ2 = impact[1]*impact[1]/impactError[2];
+             minSig3DT=std::min( minSig3DT, sqrt( SigR2 + SigZ2) );
+             maxSig3DT=std::max( maxSig3DT, sqrt( SigR2 + SigZ2) );
+	     sumIBLHits += std::max(getIBLHit(xAODwrk->listSelTracks[j]),0);
+	     sumBLHits  += std::max(getBLHit(xAODwrk->listSelTracks[j]),0);
+             if(m_fillHist && m_curTup) {
+	        ntrkBC += getIdHF(xAODwrk->listSelTracks[j]);
+	        ntrkI  += getG4Inter(xAODwrk->listSelTracks[j]);
+             }
+          }
+	  float vProb=TMath::Prob(curVrt.chi2, 2*nth-3);
+          float cosSVPVM=ProjSV_PV(curVrt.vertex, PrimVrt, curVrt.vertexMom);
+	  float vrtR=curVrt.vertex.perp();
+	  TLorentzVector SVPV(curVrt.vertex.x()-PrimVrt.x(),curVrt.vertex.y()-PrimVrt.y(),curVrt.vertex.z()-PrimVrt.z(), 10.);
+          if(m_fillHist){
+             if( m_curTup && nth>1 ){
+                VrtVrtDist(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif3D); 
+                float Dist2D=VrtVrtDist2D(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif2D); 
+                m_curTup->NVrtTrk   [m_curTup->nNVrt] = nth;          
+                m_curTup->NVrtTrkHF [m_curTup->nNVrt] = ntrkBC;          
+                m_curTup->NVrtTrkI  [m_curTup->nNVrt] = ntrkI;          
+                m_curTup->NVrtProb  [m_curTup->nNVrt] = vProb;          
+                m_curTup->NVrtSig3D [m_curTup->nNVrt] = signif3D;
+                m_curTup->NVrtSig2D [m_curTup->nNVrt] = signif2D;
+                m_curTup->NVrtDist2D[m_curTup->nNVrt] = vrtR<20. ? Dist2D : vrtR;
+                m_curTup->NVrtM     [m_curTup->nNVrt] = curVrt.vertexMom.M();
+                m_curTup->NVrtPt    [m_curTup->nNVrt] = curVrt.vertexMom.Pt();
+                m_curTup->NVrtEta   [m_curTup->nNVrt] = SVPV.Eta();
+                m_curTup->NVrtIBL   [m_curTup->nNVrt] = sumIBLHits;
+                m_curTup->NVrtBL    [m_curTup->nNVrt] = sumBLHits;
+                m_curTup->NVrtSinSPM[m_curTup->nNVrt] = sqrt(1.-cosSVPVM*cosSVPVM);
+                m_curTup->NVrtCh    [m_curTup->nNVrt] = curVrt.vertexCharge;
+                m_curTup->NVMinPtT  [m_curTup->nNVrt] = minPtT;
+                m_curTup->NVMinS3DT [m_curTup->nNVrt] = minSig3DT;
+                m_curTup->NVrtBDT   [m_curTup->nNVrt] = 1.1;
+                if( m_curTup->nNVrt < DevTuple::maxNVrt-1 )m_curTup->nNVrt++;
+            }
+          }
+//-------------------BDT based rejection
+          if(nth==2){
+	     if(curVrt.vertexMom.Pt() > m_Vrt2TrPtLimit){ curVrt.Good = false; continue; }
+             float rhit0=xAODwrk->listSelTracks[curVrt.selTrk[0]]->radiusOfFirstHit();
+             float rhit1=xAODwrk->listSelTracks[curVrt.selTrk[1]]->radiusOfFirstHit();
+	     VrtVrtDist(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif3D); 
+	     float Dist2D=VrtVrtDist2D(PrimVrt,curVrt.vertex, curVrt.vertexCov, signif2D); 
+	     std::vector<float> VARS(10);
+	     VARS[0]=vProb;
+	     VARS[1]=log(curVrt.vertexMom.Pt());
+	     VARS[2]=log(std::max(minPtT,m_cutPt));
+	     VARS[3]=log(vrtR<20. ? Dist2D : vrtR);
+	     VARS[4]=log(std::max(minSig3DT,m_trkSigCut));
+	     VARS[5]=log(maxSig3DT);
+	     VARS[6]=curVrt.vertexMom.M();
+	     VARS[7]=sqrt(fabs(1.-cosSVPVM*cosSVPVM));
+	     VARS[8]=SVPV.Eta();
+	     VARS[9]=std::max(rhit0,rhit1);
+	     //VARS[9]=sumIBLHits;
+	     //VARS[10]=sumBLHits;
+	     //VARS[4]=std::max(signif3D,m_selVrtSigCut);
+	     float wgtSelect=m_SV2T_BDT->GetGradBoostMVA(VARS);
+	     //std::vector<float> weights=m_SV2T_BDT->GetMultiResponse(VARS,3);
+	     //float wgtSelect=weights[0];
+	     if(m_fillHist){
+	       m_hb_fakeSVBDT->Fill(wgtSelect,1.);
+	       if( m_curTup ) m_curTup->NVrtBDT[m_curTup->nNVrt-1] = wgtSelect;
+	     }
+	     if(wgtSelect<m_v2tFinBDTCut) curVrt.Good = false;
+	   }
+    }
+//
+//--Final cleaning of the 1-track vertices set. Must be behind all other cleanings.
+//-- Debug ntuple for 1track vertex is filled here as well
+//
+    if(m_multiWithOneTrkVrt) Clean1TrVertexSet(WrkVrtSet);
+    if(m_fillHist && m_curTup && m_multiWithOneTrkVrt){
+      for(auto & V : (*WrkVrtSet)) {
+        nth=V.selTrk.size();
+        if( !V.Good || nth != 1 ) continue;  // Good 1track vertices
+        m_fitSvc->VKalGetImpact(xAODwrk->listSelTracks[V.selTrk[0]], PrimVrt.position(), 1, impact, impactError);
+        int ntrkBC = getIdHF(xAODwrk->listSelTracks[V.selTrk[0]]);
+	double SigR2 = impact[0]*impact[0]/impactError[0];
+	double SigZ2 = impact[1]*impact[1]/impactError[2];
+        float Dist2D=VrtVrtDist2D(PrimVrt,V.vertex, V.vertexCov, signif2D); 
+        m_curTup->NVrtTrk   [m_curTup->nNVrt] = nth;          
+        m_curTup->NVrtTrkHF [m_curTup->nNVrt] = ntrkBC;          
+        m_curTup->NVrtProb  [m_curTup->nNVrt] = TMath::Prob(V.chi2, 1);        
+        m_curTup->NVrtSig3D [m_curTup->nNVrt] = 0.;
+        m_curTup->NVrtSig2D [m_curTup->nNVrt] = signif2D;
+        m_curTup->NVrtDist2D[m_curTup->nNVrt] = Dist2D;
+        m_curTup->NVrtM     [m_curTup->nNVrt] = V.vertexMom.M();
+        m_curTup->NVrtPt    [m_curTup->nNVrt] = V.vertexMom.Pt();
+        m_curTup->NVrtSinSPM[m_curTup->nNVrt] = 0.;
+        m_curTup->NVrtCh    [m_curTup->nNVrt] = V.vertexCharge;
+        m_curTup->NVMinPtT  [m_curTup->nNVrt] = xAODwrk->listSelTracks[V.selTrk[0]]->pt();
+        m_curTup->NVMinS3DT [m_curTup->nNVrt] = sqrt(SigR2 + SigZ2);
+        m_curTup->NVrtBDT   [m_curTup->nNVrt] = 1.1;
+        if( m_curTup->nNVrt < DevTuple::maxNVrt-1 )m_curTup->nNVrt++;
+   }  }
+//-------------------------------------------
+//Checks
+    std::vector<WrkVrt> GoodVertices(0);
+    nGoodVertices=0;         // Final number of good vertices
+    n2trVrt=nNtrVrt=0;       // N of vertices with different amount of tracks
+    for(auto & iv : (*WrkVrtSet) ) {
+       nth=iv.selTrk.size(); if(nth == 0) continue;   /* Definitely bad vertices */
+       if( iv.Good) {
+	  nGoodVertices++;                                    
+	  GoodVertices.emplace_back(iv);    /* add it */
+	  if(nth==2)n2trVrt++;
+	  if(nth>=3)nNtrVrt++;
+       }
+    }
+    if(nGoodVertices == 0 || (n2trVrt+nNtrVrt)==0){  // No good vertices at all
+      delete WrkVrtSet;  delete TrkInVrt;
+      if(m_fillHist && m_curTup ) m_curTup->nNVrt=0;
+      return finalVertices;
+    }
+//
+//sorting
+    while(1){ bool swapDone=false;                              // Sort on XY distance from (0.,0.)
+      for(int iv=0; iv<(int)GoodVertices.size()-1; iv++) {
+        if( GoodVertices[iv].vertex.perp() > GoodVertices[iv+1].vertex.perp()){
+	  std::swap( GoodVertices[iv], GoodVertices[iv+1] );
+          swapDone=true; 
+        }
+      }    if(!swapDone) break;
+    }
+    while(1){ bool swapDone=false;                            // Then sort on Projected dist if R<20.
+      for(int iv=0; iv<(int)GoodVertices.size()-1; iv++) {
+        if(GoodVertices[iv+1].vertex.perp() > 400.) continue;
+        if(GoodVertices[iv].projectedVrt > GoodVertices[iv+1].projectedVrt){
+	  std::swap( GoodVertices[iv], GoodVertices[iv+1] );
+          swapDone=true; 
+        }
+      }    if(!swapDone) break;
+    }
+    if(nGoodVertices>1){
+      if( GoodVertices[1].vertexMom.M()-GoodVertices[0].vertexMom.M() > 5000.) std::swap( GoodVertices[0], GoodVertices[1] );
+    }
+    if(m_fillHist){m_hb_distVV->Fill( minVrtVrtDist( WrkVrtSet, foundV1, foundV2), m_w_1); }
+//-------------------------------------------
+// Saving and final cleaning
+//
+    nGoodVertices=0;         // Final number of good vertices
+    int n1trVrt=0;           // Final number of good 1-track vertices
+    TLorentzVector VertexMom;
+    for(int iv=0; iv<(int)GoodVertices.size(); iv++) {
+          nth=GoodVertices[iv].selTrk.size();
+          xAODwrk->tmpListTracks.clear();
+          for(i=0;i<nth;i++) {
+             j=GoodVertices[iv].selTrk[i];                           /*Track number*/
+             xAODwrk->tmpListTracks.push_back( xAODwrk->listSelTracks[j] );
+          }
+          if(m_fillHist){ 
+	     m_hb_totmass->Fill(GoodVertices[iv].vertexMom.M(), m_w_1);
+             m_hb_r2d->Fill( GoodVertices[iv].vertex.perp(), m_w_1); } 
+// xAOD::Vertex creation-----------------------------
+          xAOD::Vertex * tmpVertex=new xAOD::Vertex();
+          tmpVertex->makePrivateStore();
+          tmpVertex->setPosition(GoodVertices[iv].vertex);
+          int NERMS=GoodVertices[iv].vertexCov.size();
+	  NERMS=6;
+          std::vector<float> floatErrMtx;   floatErrMtx.resize(NERMS);
+          for(int i=0; i<NERMS; i++) floatErrMtx[i]=GoodVertices[iv].vertexCov[i];
+          tmpVertex->setCovariance(floatErrMtx);
+          tmpVertex->setFitQuality(GoodVertices[iv].chi2, (float)(nth*2-3));
+
+          std::vector<Trk::VxTrackAtVertex> & tmpVTAV=tmpVertex->vxTrackAtVertex();    tmpVTAV.clear();
+          for(int ii=0; ii<nth; ii++) {
+             AmgSymMatrix(5) *CovMtxP=new AmgSymMatrix(5);    (*CovMtxP).setIdentity(); 
+             Trk::Perigee * tmpMeasPer  =  new Trk::Perigee( 0.,0.,  GoodVertices[iv].trkAtVrt[ii][0], 
+	                                                             GoodVertices[iv].trkAtVrt[ii][1],
+                                                                     GoodVertices[iv].trkAtVrt[ii][2],
+                                                                Trk::PerigeeSurface(GoodVertices[iv].vertex), CovMtxP );
+             tmpVTAV.push_back( Trk::VxTrackAtVertex( 1., tmpMeasPer) );
+	     if(xAODwrk){            //No way to store a link to Rec::TrackParticleContainer 
+               ElementLink<xAOD::TrackParticleContainer> TEL;  TEL.setElement( xAODwrk->tmpListTracks[ii] );
+               const xAOD::TrackParticleContainer* cont = (const xAOD::TrackParticleContainer* ) (xAODwrk->tmpListTracks[ii]->container() );
+	       TEL.setStorableObject(*cont);
+               tmpVertex->addTrackAtVertex(TEL,1.);
+	     }
+          }
+          finalVertices.push_back(tmpVertex);
+//-----
+          nGoodVertices++;
+          if(nth==1)n1trVrt++;
+//-----
+           VertexMom += GoodVertices[iv].vertexMom;
+    }
+    if(m_fillHist){
+      m_hb_goodvrtN->Fill( nGoodVertices+0.1, m_w_1);
+      m_hb_goodvrt1N->Fill( n1trVrt+0.1, m_w_1);
+    }
+
+
+    if(nGoodVertices == 0){
+      delete WrkVrtSet;
+      delete TrkInVrt;
+      return finalVertices;
+    }
+
+//-----------------------------------------------------------------------------------
+//  Saving of results
+//
+//
+
+
+      delete WrkVrtSet; delete TrkInVrt;
+
+      return finalVertices;
+
+
+  }
+
+
+} //end namespace
+
+
diff --git a/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/components/NewVrtSecInclusiveTool_entries.cxx b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/components/NewVrtSecInclusiveTool_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..245d17b9d69d448ffb1fbb235aebb787298a3f1f
--- /dev/null
+++ b/Reconstruction/VKalVrt/NewVrtSecInclusiveTool/src/components/NewVrtSecInclusiveTool_entries.cxx
@@ -0,0 +1,7 @@
+#include "NewVrtSecInclusiveTool/NewVrtSecInclusiveTool.h"
+
+using namespace Rec;
+
+DECLARE_COMPONENT( NewVrtSecInclusiveTool )
+
+
diff --git a/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDPhysValMonitoringConfig.py b/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDPhysValMonitoringConfig.py
index f08a8b013d43287ba3f9a28a48ea6aaf427a776d..1fc3ac1d3b0ff4064af328641f301137e1c5c23e 100644
--- a/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDPhysValMonitoringConfig.py
+++ b/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDPhysValMonitoringConfig.py
@@ -123,7 +123,9 @@ def TrigIDPhysValMonitoringTool( legacy_monitoring=False ):
     if mt_chains:
       chainnames = [
         "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_FTF:roi=HLT_Roi_L2SAMuon",
-        "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_IDTrig:roi=HLT_Roi_L2SAMuon"
+        "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_FTF:roi=HLT_Roi_L2SAMuonForEF",
+        "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_IDTrig:roi=HLT_Roi_L2SAMuon",
+        "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_IDTrig:roi=HLT_Roi_L2SAMuonForEF"
       ]
     else:
       chainnames = [
diff --git a/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDtrkMonitoringConfig.py b/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDtrkMonitoringConfig.py
index 48ebb4505f53451c9e6c1566dc954ed22271c012..55bd062918373294cd0de0d2bd72cab802146d23 100644
--- a/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDtrkMonitoringConfig.py
+++ b/Trigger/TrigMonitoring/TrigIDtrkMonitoring/python/TrigIDtrkMonitoringConfig.py
@@ -178,10 +178,9 @@ def TrigIDtrkMonitoringTool( legacy_monitoring=False ):
                         tidamuon.ntupleChainNames += [
                                 "Offline",
                                 "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_FTF:roi=HLT_Roi_L2SAMuon",
+                                "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_FTF:roi=HLT_Roi_L2SAMuonForEF",
                                 "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_IDTrig:roi=HLT_Roi_L2SAMuon",
-                                "HLT_mu.*idperf.*:key=HLT_IDTrack_MuonIso_FTF",
-                                "HLT_mu.*idperf.*:key=HLT_IDTrack_MuonIso_IDTrig",
-                                "HLT_mu.*idperf.*:key=HLT_IDTrack_MuonLate_IDTrig"
+                                "HLT_mu.*idperf.*:key=HLT_IDTrack_Muon_IDTrig:roi=HLT_Roi_L2SAMuonForEF"
                         ]
                 else:
                         tidamuon.ntupleChainNames += [
diff --git a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
index a5775365246c8f1726071837f5f7c752df58f1ce..ecb012901a29d84399e670888d8512770cb15304 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
+++ b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.cxx
@@ -18,7 +18,7 @@ using TrigCompositeUtils::newDecisionIn;
 
 RoRSeqFilter::RoRSeqFilter( const std::string& name, 
   ISvcLocator* pSvcLocator ) :
-  ::AthAlgorithm( name, pSvcLocator )
+  ::AthReentrantAlgorithm( name, pSvcLocator )
 {}
 
 
@@ -71,15 +71,17 @@ StatusCode RoRSeqFilter::initialize()
 }
 
 
-StatusCode RoRSeqFilter::execute() {  
+StatusCode RoRSeqFilter::execute(const EventContext& ctx) const {
   ATH_MSG_DEBUG ( "Executing " << name() << "..." );
-  auto inputHandles  = m_inputKeys.makeHandles();
-  auto outputHandles = m_outputKeys.makeHandles();
+  auto inputHandles  = m_inputKeys.makeHandles(ctx);
+  auto outputHandles = m_outputKeys.makeHandles(ctx);
 
   std::vector<std::string> inputNames({"exec", "anyvalid"});
   std::vector<bool> inputStats({true, false}); // position 0 for number of execs, always true, bool at position 1 is set later
+  inputNames.reserve(inputHandles.size() + 2);
+  inputStats.reserve(inputHandles.size() + 2);
   bool validInputs = false;
-  for ( auto inputHandle: inputHandles ) {
+  for ( auto& inputHandle: inputHandles ) {
     inputNames.push_back(inputHandle.name());
     if( inputHandle.isValid() ) {// this is because input is implicit
       validInputs = true;
@@ -94,7 +96,7 @@ StatusCode RoRSeqFilter::execute() {
   Monitored::Group( m_monTool, inputStat, inputName );
   
   if (!validInputs) {
-    setFilterPassed(false);
+    setFilterPassed(false, ctx);
     ATH_MSG_DEBUG ( "No valid inputs found, filter failed. Return...." );
     return StatusCode::SUCCESS;
   }
@@ -108,25 +110,23 @@ StatusCode RoRSeqFilter::execute() {
     ATH_MSG_DEBUG( "Recording " <<  m_outputKeys[ 0 ].key() ); 
     createAndStore(outputHandles[0]);
     DecisionContainer* output = outputHandles[0].ptr();
-    for ( auto inputKey: m_inputKeys ) {
-      auto inputHandle = SG::makeHandle( inputKey );
-      if( inputHandle.isValid() )
+    for ( auto& inputHandle: inputHandles) {
+      if( inputHandle.isValid() ) {
         passCounter += copyPassing( *inputHandle,  *output );
+      }
     }
     outputIndex++;
 
   } else { // Not merging inputs
 
-    for ( auto inputKey: m_inputKeys ) {
-      // already made handles, so this code could be simplified to a loop over inputHandles.
-      auto inputHandle = SG::makeHandle( inputKey );
+    for ( auto& inputHandle: inputHandles ) {
 
       if( not inputHandle.isValid() ) {
-        ATH_MSG_DEBUG( "InputHandle "<< inputKey.key() <<" not present" );
+        ATH_MSG_DEBUG( "InputHandle "<< inputHandle.key() <<" not present" );
       } else if ( inputHandle->empty() ) {
-        ATH_MSG_DEBUG( "InputHandle "<< inputKey.key() <<" contains all rejected decisions, skipping" );
+        ATH_MSG_DEBUG( "InputHandle "<< inputHandle.key() <<" contains all rejected decisions, skipping" );
       } else {
-        ATH_MSG_DEBUG( "Checking inputHandle: "<< inputKey.key() <<" has " << inputHandle->size() <<" elements");
+        ATH_MSG_DEBUG( "Checking inputHandle: "<< inputHandle.key() <<" has " << inputHandle->size() <<" elements");
         createAndStore(outputHandles[outputIndex]);
         DecisionContainer* output = outputHandles[outputIndex].ptr();
         passCounter += copyPassing( *inputHandle, *output );  
@@ -134,13 +134,12 @@ StatusCode RoRSeqFilter::execute() {
       }
       outputIndex++; // Keep the mapping of inputKey<->outputKey correct
     }
-
   }
 
-  setFilterPassed( passCounter != 0 );
-  ATH_MSG_DEBUG( "Filter " << ( filterPassed() ? "passed" : "rejected") <<"; creating "<< outputIndex<<" valid outDecisions DH:");
+  setFilterPassed( passCounter != 0, ctx );
+  ATH_MSG_DEBUG( "Filter " << ( filterPassed(ctx) ? "passed" : "rejected") <<"; creating "<< outputIndex<<" valid outDecisions DH:");
   if (msgLvl(MSG::DEBUG)){
-    for (auto output: outputHandles){
+    for (auto& output: outputHandles){
       if( output.isValid() ) ATH_MSG_DEBUG(" "<<output.key());
     }
   }
diff --git a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h
index cfb712abc0bcbcac2fd0c344e0d5ee5f2cc685ed..ac24edb149317fb1dd4986f82cfd09575b60de35 100644
--- a/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h
+++ b/Trigger/TrigSteer/DecisionHandling/src/RoRSeqFilter.h
@@ -7,7 +7,7 @@
 #include <string>
 #include <set>
 
-#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
 #include "AthContainers/ConstDataVector.h"
 #include "TrigCompositeUtils/TrigCompositeUtils.h"
 #include "TrigCompositeUtils/HLTIdentifier.h"
@@ -44,7 +44,7 @@
  **/
 
 class RoRSeqFilter
-  : public ::AthAlgorithm
+  : public ::AthReentrantAlgorithm
 { 
  public: 
   RoRSeqFilter( const std::string& name, ISvcLocator* pSvcLocator );
@@ -58,7 +58,7 @@ class RoRSeqFilter
  * @brief Apply this filter in-between Steps of trigger execution. Fully implicit inputs, requires Control Flow to unlock.
  * will signal a negative filter result to the Scheduler if zero chains remain active upon termination.
  **/
-  virtual StatusCode  execute() override;
+  virtual StatusCode  execute(const EventContext& ctx) const override;
 
  private:
   RoRSeqFilter();
diff --git a/Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mp_grid.py b/Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mt_grid.py
similarity index 97%
rename from Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mp_grid.py
rename to Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mt_grid.py
index e417f55a46a1345fbc3f1c68199573342220fb0a..19ba137045c02c905eac2614fc66a40403af595d 100755
--- a/Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mp_grid.py
+++ b/Trigger/TrigValidation/TrigInDetValidation/test/test_trigID_all_ttbar_pu80_mt_grid.py
@@ -92,9 +92,8 @@ preexec_all = ';'.join([
 rdo2aod = ExecStep.ExecStep()
 rdo2aod.type = 'Reco_tf'
 rdo2aod.max_events = 1000 # TODO: 2000 events
-#rdo2aod.threads = 1 # TODO: change to 4
-#rdo2aod.concurrent_events = 1 # TODO: change to 4
-rdo2aod.forks = 4 
+rdo2aod.threads = 1 # TODO: change to 4
+rdo2aod.concurrent_events = 4 
 rdo2aod.perfmon = False
 rdo2aod.args = '--outputAODFile=AOD.pool.root --steering="doRDO_TRIG" '
 if local:
diff --git a/Trigger/TriggerCommon/TriggerJobOpts/python/Lvl1SimulationConfig.py b/Trigger/TriggerCommon/TriggerJobOpts/python/Lvl1SimulationConfig.py
index beb53063b7a6694bdafa103a80888da9a0ac69f4..6794393247cb09762dded97b37abc6c358f9cb6f 100644
--- a/Trigger/TriggerCommon/TriggerJobOpts/python/Lvl1SimulationConfig.py
+++ b/Trigger/TriggerCommon/TriggerJobOpts/python/Lvl1SimulationConfig.py
@@ -139,6 +139,9 @@ def Lvl1SimulationSequence( flags = None ):
         muctpi = L1Muctpi()
         muctpi.LVL1ConfigSvc = svcMgr.LVL1ConfigSvc
 
+    # Sets up and configures the muon alignment and detector manager
+    from MuonRecExample import MuonAlignConfig # noqa: F401
+
     l1MuonSim = seqAND("l1MuonSim", [
         
         MuonRdoToMuonDigit( "MuonRdoToMuonDigit",