diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/CMakeLists.txt b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/CMakeLists.txt
index 5963f3b0a3b48794c88103b07ca966421751a38f..f66377acc4698afa16361d8be73dfd72ba3e78bd 100644
--- a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/CMakeLists.txt
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/CMakeLists.txt
@@ -1,12 +1,23 @@
 # The name of the package:
 atlas_subdir( FTagAnalysisInterfaces )
 
+# The dependencies of the package:
+atlas_depends_on_subdirs(
+   PUBLIC
+   Control/AthToolSupport/AsgTools
+   Event/xAOD/xAODBTagging
+   Event/xAOD/xAODJet
+   PhysicsAnalysis/AnalysisCommon/PATCore
+   PhysicsAnalysis/AnalysisCommon/PATInterfaces
+   PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface
+   PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency )
+
 # Component(s) in the package:
 atlas_add_library( FTagAnalysisInterfacesLib
    FTagAnalysisInterfaces/*.h
    INTERFACE
    PUBLIC_HEADERS FTagAnalysisInterfaces
-   LINK_LIBRARIES AsgTools xAODBTagging xAODJet PATCoreLib CalibrationDataInterfaceLib PATInterfaces xAODBTaggingEfficiencyLib )
+   LINK_LIBRARIES AsgTools xAODBTagging xAODJet PATCoreLib CalibrationDataInterfaceLib )
 
 atlas_add_dictionary( FTagAnalysisInterfacesDict
    FTagAnalysisInterfaces/FTagAnalysisInterfacesDict.h
diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/FTagAnalysisInterfacesDict.h b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/FTagAnalysisInterfacesDict.h
index 82af707e72e1ff200b8e202825c581992107b215..8a00bd1d5312c8757bc0f95d16b9e04250354f5f 100644
--- a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/FTagAnalysisInterfacesDict.h
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/FTagAnalysisInterfacesDict.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 
@@ -15,5 +15,6 @@
 #include "FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h"
 #include "FTagAnalysisInterfaces/IBTaggingSelectionTool.h"
 #include "FTagAnalysisInterfaces/IBTaggingTruthTaggingTool.h"
+#include "FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h"
 
 #endif // FTAGANALYSISINTERFACES_FTAGANALYSISINTERFACESDICT_H
diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h
index 106f523b0decde966b92e42d989ea5c7eff10688..18cd37db05233cc780771e903bb401ef7710beca 100644
--- a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -76,6 +76,8 @@ class IBTaggingEfficiencyTool : virtual public CP::ISystematicsTool {
 
   // this merely passes on the request to the underlying CDI object (listSystematics() cannot be used here, as corresponding CP::SystematicVariation objects may not exist)
   virtual std::map<std::string, std::vector<std::string> > listScaleFactorSystematics(bool named = false) const = 0;
+
+  virtual CP::CorrectionCode getEigenRecompositionCoefficientMap(const std::string &label, std::map<std::string, std::map<std::string, float>> & coefficientMap) = 0;
 };
 
 #endif // CPIBTAGGINGEFFICIENCYTOOL_H
diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..711f0a436a0b531e3dc4eeefc1b1d9474b55c385
--- /dev/null
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h
@@ -0,0 +1,63 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IBTaggingEfficiencyTool.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+/**
+@class BTaggingEigenVectorRecompositionTool
+Tool to help retrieving(from CDI) and providing coefficents values which
+could be used for expressing eigen vector NPs by linear combination of
+original uncertainty NPs in workspace level of the physics analysis.
+Then eigenvector uncertainties are replaced by original uncertainties.
+Replacement could help us correlate uncertainties between analyses
+which are using different tagger algorighthms.
+@author Y. Ke, Q. Buat
+@contact yake@cern.ch, qbuat@cern.ch
+**/
+#ifndef CPIBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
+#define CPIBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
+
+#include "AsgTools/IAsgTool.h"
+#include "PATInterfaces/ISystematicsTool.h"
+#include "PATInterfaces/CorrectionCode.h"
+#include "PATInterfaces/SystematicCode.h"
+#include "PATInterfaces/SystematicSet.h"
+
+#include <vector>
+#include <map>
+
+class IBTaggingEigenVectorRecompositionTool : virtual public CP::ISystematicsTool {
+
+  /// Declare the interface that the class provides
+  ASG_TOOL_INTERFACE( IBTagEigenVectorRecompositionTool )
+
+  public:
+  /**
+   * Return a vector which contains a list of original vector uncertainties names.
+   * vector list is for the chosen flavour label. The order of the names is the same
+   * as the coefficient values given by getCoefficients()  
+   **/
+  virtual std::vector<std::string> getListOfOriginalNuisanceParameters(const std::string& label) const = 0;
+    /**
+   * Produce a coefficient map contains only eigenvectors that is showing in
+   * eigenIdxList and return it to user. If given empty evIdxList, the function
+   * returns a full map. Produced map is for the chosen flavour label.
+   **/
+  virtual std::map<std::string, std::map<std::string, float>> getCoefficientMap(const std::string& label, const std::vector<unsigned int> eigenIdxList = std::vector<unsigned int>()) const = 0;
+  /**
+   * Returns a vector contains the coefficients value of the chosen label
+   * and the chosen eigenvector. The order of the value is the same as
+   * the order of original uncertainty names given by
+   * getListOfOriginalNuisanceParameters()
+   **/
+  virtual std::vector<float> getCoefficients(const std::string & label, const unsigned int evIdx) const = 0;
+  // Return number of eigenvectors used for the chosen label.
+  virtual int getNumEigenVectors(const std::string & label) const = 0;
+
+};
+
+#endif // CPIBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingSelectionTool.h b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingSelectionTool.h
index 4a2962e9912563c1402f153ccd3e30d85a2a4ea3..01f249278c851d790a114d67409cecc6f1a7bc79 100644
--- a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingSelectionTool.h
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/IBTaggingSelectionTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/selection.xml b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/selection.xml
index 0ca83586057e2ac71082c4616505608f9d868646..da7589e410ea809716db296417f176b935a6e4ba 100644
--- a/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/selection.xml
+++ b/PhysicsAnalysis/Interfaces/FTagAnalysisInterfaces/FTagAnalysisInterfaces/selection.xml
@@ -3,4 +3,5 @@
   <class name="IBTaggingEfficiencyTool" />
   <class name="IBTaggingSelectionTool" />
    <class name="IBTaggingTruthTaggingTool" />
+   <class name="IBTaggingEigenVectorRecompositionTool" />
 </lcgdict>
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CMakeLists.txt b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CMakeLists.txt
index 4fb473ce926d96247f45ac7182f85274e0cfacf0..1901242e9dea21f80be95642d9eb30b6369670d6 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CMakeLists.txt
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CMakeLists.txt
@@ -31,3 +31,4 @@ atlas_add_library( CalibrationDataInterfaceLib
 
 # Install files from the package:
 atlas_install_joboptions( share/*.py )
+
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataBackend.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataBackend.h
index 9e3a745a7da7846c8aa286aae6508833f3139a2d..7da15c5882ca096efdd0234a089c80caf694bc17 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataBackend.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataBackend.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataContainer.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataContainer.h
index 1b922479b4f8d784871fe3abfab466e072e9e763..7de76d26c6a5b46f6485b440b75172a258c8801f 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataContainer.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataContainer.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataEigenVariations.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataEigenVariations.h
index c2eb5e166a586c1c497779d48004f24de5a09618..9f9b8a3bb7a3c4d88255b71ea393b5b1f589e59d 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataEigenVariations.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataEigenVariations.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////
@@ -87,6 +87,10 @@ namespace Analysis
     /** matrix to remove unecessary rows and columns from covariance */
     TMatrixD    getJacobianReductionMatrix() const;
 
+    /** Eigenvector recomposition method.*/
+    bool EigenVectorRecomposition(const std::string label,
+				  std::map<std::string, std::map<std::string, float>> &coefficientMap) const;
+
   private:
     /** container object containing the basic information */
     const CalibrationDataHistogramContainer* m_cnt;
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceBase.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceBase.h
index a35c2462babf9f241d6fb880ecce6c160c52c7ab..5e83f573253c044de4878317ea46ce5f0a2ac98b 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceBase.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceBase.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceROOT.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceROOT.h
index 215d1e03076b70be74e9f8ccce7b15cfe574b549..96311d58e5b5d47bc8a90b31aa3ff3f2469196b4 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceROOT.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceROOT.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -98,11 +98,8 @@ namespace Analysis
 				   const std::map<std::string, std::vector<std::string> >& EffNames,
 				   const std::map<std::string, std::vector<std::string> >& excludeFromEV,
 				   const std::map<std::string, Analysis::EVReductionStrategy> EVReductions,
-
-				   bool useEV = true,
-				   bool useMCMCSF = true,
-				   bool useTopologyRescaling = false,
-     				   bool useRecommendedEVExclusions = false,
+				   bool useEV = true, bool useMCMCSF = true,
+				   bool useTopologyRescaling = false, bool useRecommendedEVExclusions = false,
 				   bool verbose = true);
 
       /** default constructor for PROOF object retrieval */
@@ -306,6 +303,20 @@ namespace Analysis
 
       // ------------------------------------------------------------------------------------------
 
+      /** run EigenVector Recomposition method */
+      CalibrationStatus runEigenVectorRecomposition(const std::string& author,
+						    const std::string& label,
+						    const std::string& OP,
+						    unsigned int mapindex = 0);
+      
+      CalibrationStatus runEigenVectorRecomposition(const std::string& label,
+						    unsigned int mapindex = 0);
+      
+      /** Get Eigenvector recomposition map after running runEigenVectorRecomposition()*/
+      std::map<std::string, std::map<std::string, float>> getEigenVectorRecompositionCoefficientMap();
+
+      // ------------------------------------------------------------------------------------------
+
       // Utilities
 
       /** retrieve the MC efficiency (central values) object for the given flavour label and operating point.
@@ -439,6 +450,11 @@ namespace Analysis
 
       // ------------------------------------------------------------------------------------------
 
+      // map storing coefficient calculated by EigenRecomposition.
+      std::map<std::string, std::map<std::string, float>> m_coefficientMap;
+
+      // ------------------------------------------------------------------------------------------
+
       // Bounds checking functionality
 
       /** |eta| bounds and strategy for dealing with out-of-bounds conditions */
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTester.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTester.h
index b6172af5ea224ca0ece92b351d3f37750246a532..7f0856e26bca383d955a36e6264cabfb69821a73 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTester.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTester.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTool.h
index 30bc56ac344381a02730acd7e7e46b512f2d5d0c..d0a1e87e9f6c1839835e4528e3073cc803722da5 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTool.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInterfaceTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -56,7 +56,7 @@ namespace Analysis
       verify that the aliasing is appropriate!
 
       DB representation (all residing under a common root folder):
-      .../\<jet author\>/\<tagger\>/\<operating point\>/\<flavour\>/\<object name\>
+      .../<jet author>/<tagger>/<operating point>/<flavour>/<object name>
 
       @author  Frank Filthaut <F.Filthaut@science.ru.nl>
   */  
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInternals.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInternals.h
index b057529a26bce0cd28f921f242804c1f7c6e0589..779779c40eb7087596ffde95b751a555c9dc3bb7 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInternals.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataInternals.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUpdater.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUpdater.h
index 5b721f27f8a24bb4998d48d0903ad4b539e9265a..0cda9c22e6e745b0b4a654780f6d576eaa2e519f 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUpdater.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUpdater.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUtilities.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUtilities.h
index 4c334edf114e1e402a9581a114686cb28b3a87ea..e9d74cc6a14a0d67c996e1b17a089398393d4d6d 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUtilities.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataUtilities.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 // CalibrationDataUtilities.h, (c) ATLAS Detector software
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataVariables.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataVariables.h
index 8fb1b49ff84da94a5d3a95db114d4511b8b27f6c..f548030e07e2956d5a3cf1cea2ad3fa871e7b04c 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataVariables.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/CalibrationDataVariables.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/ICalibrationDataInterfaceTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/ICalibrationDataInterfaceTool.h
index acb43e2034ded557a4d5aa4577d028118c02e552..f813f04639257a5c9e33b6fac5afd371abc06c61 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/ICalibrationDataInterfaceTool.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/CalibrationDataInterface/ICalibrationDataInterfaceTool.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataBackend.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataBackend.cxx
index 3505ea574d3595c52a3331af0afd40b6d743481c..4e2cc51d005895134696342cc4cb3f6aa8b1eb5e 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataBackend.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataBackend.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataContainer.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataContainer.cxx
index 5688046d1392ce14befae3cfd57653cd1ad062f6..a4282a8e0e9b9c1ce05cc070d82be6fb21427df1 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataContainer.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataContainer.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataEigenVariations.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataEigenVariations.cxx
index 31375312c8240a29323360ea85055ddead9ff2c8..2210f43fa510939f31e1492d516a6135ca2afb3d 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataEigenVariations.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataEigenVariations.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////////
@@ -23,6 +23,7 @@
 #include "TDecompSVD.h"
 #include "TMatrixDSymEigen.h"
 #include "TROOT.h"
+#include "TFile.h"
 
 using Analysis::CalibrationDataEigenVariations;
 using Analysis::CalibrationDataInterface::split;
@@ -1040,3 +1041,134 @@ CalibrationDataEigenVariations::isExtrapolationVariation(unsigned int nameIndex)
 
   return (m_namedExtrapolation == int(nameIndex));
 }
+
+//________________________________________________________________________________
+bool
+CalibrationDataEigenVariations::EigenVectorRecomposition(const std::string label, 
+							 std::map<std::string, std::map<std::string, float>> &coefficientMap) const
+{
+  // Calculating eigen vector recomposition coefficient map and pass to
+  // user by reference. Return true if method success. Return false and
+  // will not modify coefficientMap if function failed.
+  //
+  //     label:          flavour label
+  //     coefficientMap: (reference to) coefficentMap which will be used as return value.
+  if (! m_initialized) const_cast<CalibrationDataEigenVariations*>(this)->initialize();
+
+  std::vector<TH1*> originSF_hvec;
+  std::vector<TH1*> eigenSF_hvec;
+
+  // Retrieving information for calculation
+  std::vector<string>fullUncList = m_cnt->listUncertainties();
+  std::vector<string> uncList;
+  for (unsigned int t = 0; t < fullUncList.size(); ++t) {
+    // entries that should never be included
+    if (fullUncList[t] == "comment" || fullUncList[t] == "result" ||
+	fullUncList[t] == "combined" || fullUncList[t] == "statistics" ||
+        fullUncList[t] == "systematics" || fullUncList[t] == "MCreference" ||
+        fullUncList[t] == "MChadronisation" || fullUncList[t] == "extrapolation" ||
+        fullUncList[t] == "ReducedSets" || fullUncList[t] == "excluded_set") continue;
+    // entries that can be excluded if desired
+    if (m_namedIndices.find(fullUncList[t]) != m_namedIndices.end()) continue;
+    
+    TH1* hunc = dynamic_cast<TH1*>(m_cnt->GetValue(fullUncList[t].c_str()));
+
+    Int_t nx = hunc->GetNbinsX();
+    Int_t ny = hunc->GetNbinsY();
+    Int_t nz = hunc->GetNbinsZ();
+    Int_t bin = 0;
+    bool retain = false; // Retain the histogram?
+
+    // discard empty histograms
+    // Read all bins without underflow&overflow
+    for(Int_t binx = 1; binx <= nx; binx++)
+      for(Int_t biny = 1; biny <= ny; biny++)
+	for(Int_t binz = 1; binz <= nz; binz++){
+	  bin = hunc->GetBin(binx, biny, binz);  
+	  if (fabs(hunc->GetBinContent(bin)) > 1E-20){
+	    retain = true;
+	    break;
+	  }
+	}// end hist bin for-loop
+    if (!retain){
+      std::cout<<"Eigenvector Recomposition: Empty uncertainty "<<fullUncList.at(t)<<" is discarded."<<std::endl;
+      continue; // discard the vector
+    }
+
+    uncList.push_back(fullUncList.at(t));
+    originSF_hvec.push_back(hunc);
+  }
+
+  TH1* nom = dynamic_cast<TH1*>(m_cnt->GetValue("result")); // Nominal SF hist
+  int dim = nom->GetDimension();
+  Int_t nx = nom->GetNbinsX();
+  Int_t ny = nom->GetNbinsY();
+  Int_t nz = nom->GetNbinsZ();
+  Int_t nbins = nx;
+  if(dim > 1) nbins *= ny;
+  if(dim > 2) nbins *= nz;
+  TMatrixD matSF(uncList.size(), nbins);
+  Int_t col = 0; // mark the column number
+  // Fill the Delta SF Matrix
+  for(unsigned int i = 0; i < uncList.size(); i++){
+    col = 0;
+    // Loop all bins except underflow&overflow bin
+    for(int binz = 1; binz <= nz; binz++)
+      for(int biny = 1; biny <= ny; biny++)
+	for(int binx = 1; binx <= nx; binx++){
+ 	  Int_t bin = originSF_hvec.at(i)->GetBin(binx, biny, binz);
+	  TMatrixDRow(matSF,i)[col] = originSF_hvec[i]->GetBinContent(bin);
+	  col++;
+	}
+  }
+
+  // get eigen vectors of scale factors. Note that this is not the original eigen-vector.
+  int nEigen = getNumberOfEigenVariations();
+  TH1* up = nullptr;
+  TH1* down = nullptr;
+  for (int i = 0; i < nEigen; i++){
+    if (!getEigenvectorVariation(i, up, down)){
+       std::cerr<<"EigenVectorRecomposition: Error on retrieving eigenvector "<<i<<std::endl;
+      return false;
+    }
+    //Need uncertainty value so subtract central calibration here.
+    up->Add(nom, -1);
+    eigenSF_hvec.push_back(up);
+  }
+  TMatrixD matEigen(nEigen, nbins);
+
+  // Fill the Eigen Matrix
+  for(int i = 0; i < nEigen; i++){
+    col = 0;
+    // Read 300 bins without underflow&overflow
+    for(int binz = 1; binz <= nz; binz++)
+      for(int biny = 1; biny <= ny; biny++)
+	for(int binx = 1; binx <= nx; binx++){
+	  Int_t bin = eigenSF_hvec.at(i)->GetBin(binx, biny, binz);
+	  TMatrixDRow(matEigen,i)[col] = eigenSF_hvec[i]->GetBinContent(bin);
+	  col++;
+	}
+  }
+
+  // Sanity check:
+  TMatrixD matEigenOriginal = matEigen;
+  TMatrixD matEigenTranspose = matEigen;
+  matEigenTranspose = matEigenTranspose.T();
+  TMatrixD matOriginalTimesTranspose = matEigenOriginal*matEigenTranspose;
+  TMatrixD matEigenInvert = matEigenTranspose*matOriginalTimesTranspose.Invert();
+  //(matEigenOriginal*matEigenInvert).DrawClone("colz"); // This should give us an identity matrix
+
+  TMatrixD matCoeff = matSF*matEigenInvert;
+  int nRows = matCoeff.GetNrows();
+  int nCols = matCoeff.GetNcols();
+  std::map<std::string, float> temp_map;
+  for (int col = 0; col < nCols; col++){
+    temp_map.clear();
+    for(int row = 0; row < nRows; row++){
+      temp_map[uncList[row]] = TMatrixDRow(matCoeff, row)[col];
+    }
+    coefficientMap["Eigen_"+label+"_"+std::to_string(col)] = temp_map;
+  }
+  
+  return true;
+}
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceBase.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceBase.cxx
index 70341de9510ceaebb9aaf58ddca238464c7f46e2..2acf618b10da806872f961376835a5d2775a8357 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceBase.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceBase.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceROOT.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceROOT.cxx
index e541ff01dcebd2c2ca7dce1be60486adda47f529..8a1b5fd518fd11b7a039ecfa059554218b0bc67c 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceROOT.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataInterfaceROOT.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////////////////////////////
@@ -394,7 +394,6 @@ Analysis::CalibrationDataInterfaceROOT::CalibrationDataInterfaceROOT(const strin
     for (auto const& flavour : flavours) {
       m_excludeFromCovMatrix[flavour] = to_exclude;
     }
-
     for (auto const& flavour : flavours) {
       test = "excludeFrom"; test += flavour; test += "CovMatrix";
       to_exclude = split(env.GetValue(test.c_str(), ""));
@@ -2158,6 +2157,72 @@ Analysis::CalibrationDataInterfaceROOT::getShiftedScaleFactors (const std::strin
   shifted->Add(hunc, sigmas);
   return shifted;
 }
+//====================== run EigenVectorRecomposition method ===========================
+Analysis::CalibrationStatus
+Analysis::CalibrationDataInterfaceROOT::runEigenVectorRecomposition (const std::string& author,
+								     const std::string& label,
+								     const std::string& OP,
+								     unsigned int mapIndex){
+  // run eigen vector recomposition method. If success, stored the retrieved coefficient map
+  // in m_coefficientMap and return success. Otherwise return error and keep m_coefficientMap
+  // untouched.
+  //    author:  jet collection name
+  //    label:   jet flavour label
+  //    OP:      tagger working point
+  //    mapIndex:     index to the MC efficiency map to be used. Should be 0?
+  // Todo: What is mapindex?
+  // Todo: Check the way xAODBTaggingTool initialize CDI. Check if that is the as how we are initialize CDI. 
+  if(!m_runEigenVectorMethod) {
+    cerr << "runEigenVectorRecomposition: Recomposition need to be ran with CalibrationDataInterfaceRoot initialized in eigenvector mode" << endl;
+    return Analysis::kError;
+  }
+  
+  unsigned int indexSF;
+  if (! retrieveCalibrationIndex (label, OP, author, true, indexSF, mapIndex)) {
+    cerr << "runEigenVectorRecomposition: unable to find SF calibration for object "
+	 << fullName(author, OP, label, true) << endl;
+    return Analysis::kError;
+  }
+
+  return runEigenVectorRecomposition (label, indexSF);
+}
+
+Analysis::CalibrationStatus
+Analysis::CalibrationDataInterfaceROOT::runEigenVectorRecomposition (const std::string& label,
+								     unsigned int indexSF){
+  // run eigen vector recomposition method. If success, stored the retrieved coefficient map
+  // in m_coefficientMap and return success. Otherwise return error and keep m_coefficientMap
+  // untouched.
+  //    label:   jet flavour label  
+  //    indexSF:       index to scale factor calibration object
+  CalibrationDataContainer* container = m_objects[indexSF];
+  if (! container) {
+    cerr << "runEigenVectorRecomposition: error retrieving container!" << endl;
+    return Analysis::kError;
+  }
+
+  // Retrieve eigenvariation
+  const CalibrationDataEigenVariations* eigenVariation=m_eigenVariationsMap[container];
+  if (! eigenVariation) {
+    cerr << "runEigenVectorRecomposition: Could not retrieve eigenvector variation, while it should have been there." << endl;
+    return Analysis::kError;
+  }
+  // Doing eigenvector recomposition
+  std::map<std::string, std::map<std::string, float>> coefficientMap;
+  if(!eigenVariation->EigenVectorRecomposition(label, coefficientMap))
+    return Analysis::kError;
+
+  m_coefficientMap = coefficientMap;
+  return Analysis::kSuccess;
+}
+
+std::map<std::string, std::map<std::string, float>>
+Analysis::CalibrationDataInterfaceROOT::getEigenVectorRecompositionCoefficientMap(){
+  if(m_coefficientMap.empty())
+    cerr << "getCoefficientMap: Call runEigenVectorRecomposition() before retrieving coefficient map! " <<endl;
+  return m_coefficientMap;
+}
+
 
 //====================== put some utility functions here ===================================
 
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataUtilities.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataUtilities.cxx
index a0be063407b3094e0a6f67ca609c892bfdcbdc6d..d35793012794ff77cc3e0744f6f8929524a492df 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataUtilities.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/CalibrationDataUtilities.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 //////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/LinkDef.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/LinkDef.h
index 5324dd345f25dde217198782598b570456ff1010..7fb4c793f1f21f50034144e1d742eaaed7939b58 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/LinkDef.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/Root/LinkDef.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "CalibrationDataInterface/CalibrationDataVariables.h"
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/src/components/CalibrationDataInterface_entries.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/src/components/CalibrationDataInterface_entries.cxx
index 3958b728c9306cca846707a930439c695a67365d..6d2329172cd0b96fe9c6b7df7dd5ef3c9d6fe5e4 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/src/components/CalibrationDataInterface_entries.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/CalibrationDataInterface/src/components/CalibrationDataInterface_entries.cxx
@@ -1,3 +1,5 @@
+
+
 #include "CalibrationDataInterface/CalibrationDataInterfaceTool.h"
 #include "CalibrationDataInterface/CalibrationDataUpdater.h"
 #include "CalibrationDataInterface/CalibrationDataInterfaceTester.h"
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/CMakeLists.txt b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/CMakeLists.txt
index 59ad17fb61f2600c0180b0fe90630cba18d3f9da..2d6618ffc57ea37daf080361679fe7a122eaa970 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/CMakeLists.txt
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/CMakeLists.txt
@@ -3,6 +3,7 @@
 # Declare the package name:
 atlas_subdir( xAODBTaggingEfficiency )
 
+
 # External dependencies:
 find_package( ROOT COMPONENTS Core Hist RIO )
 
@@ -11,15 +12,16 @@ atlas_add_library( xAODBTaggingEfficiencyLib
   xAODBTaggingEfficiency/*.h Root/*.cxx
   PUBLIC_HEADERS xAODBTaggingEfficiency
   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-  LINK_LIBRARIES ${ROOT_LIBRARIES} AsgTools xAODBTagging
+  LINK_LIBRARIES ${ROOT_LIBRARIES} AsgTools AsgMessagingLib xAODBTagging
   PATCoreAcceptLib PATInterfaces CalibrationDataInterfaceLib
   FTagAnalysisInterfacesLib
-  PRIVATE_LINK_LIBRARIES PathResolver )
+  PRIVATE_LINK_LIBRARIES PathResolver AsgMessagingLib )
+
 
 if( NOT XAOD_STANDALONE )
    atlas_add_component( xAODBTaggingEfficiency
       src/*.h src/*.cxx src/components/*.cxx
-      LINK_LIBRARIES xAODJet CalibrationDataInterfaceLib AthenaBaseComps
+      LINK_LIBRARIES AsgMessagingLib xAODJet CalibrationDataInterfaceLib AthenaBaseComps
       GaudiKernel FTagAnalysisInterfacesLib xAODBTaggingEfficiencyLib )
 endif()
 
@@ -28,15 +30,23 @@ atlas_add_dictionary( xAODBTaggingEfficiencyDict
   xAODBTaggingEfficiency/selection.xml
   LINK_LIBRARIES xAODBTaggingEfficiencyLib )
 
-# Executable(s) in the package:
-if( XAOD_STANDALONE )
+# Executable(s) in the package (to be built only under AthAnalysis or in stand-alone mode):
+if( XAOD_ANALYSIS OR XAOD_STANDALONE )
    atlas_add_executable( BTaggingEfficiencyToolTester
       util/BTaggingEfficiencyToolTester.cxx
       LINK_LIBRARIES xAODBTaggingEfficiencyLib )
 
-   atlas_add_executable( BTaggingSelectionToolTester
+   atlas_add_executable( BTaggingEigenVectorRecompositionToolTester
+      util/BTaggingEigenVectorRecompositionToolTester.cxx
+      LINK_LIBRARIES xAODBTaggingEfficiencyLib )
+
+  atlas_add_executable( BTaggingSelectionToolTester
       util/BTaggingSelectionToolTester.cxx
       LINK_LIBRARIES AsgMessagingLib xAODJet xAODBTagging xAODBTaggingEfficiencyLib )
+
+    atlas_add_executable( BTaggingTruthTaggingTester
+      util/BTaggingTruthTaggingTester.cxx
+      LINK_LIBRARIES AsgMessagingLib xAODJet xAODBTagging xAODBTaggingEfficiencyLib FTagAnalysisInterfacesLib )
 endif()
 
 # Install files from the package:
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEfficiencyTool.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEfficiencyTool.cxx
index 7082d2dd9803c302c004c12d2f65fe2188034bf2..6191e9cac88b7e09cf6ee98797141b96e9f32455 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEfficiencyTool.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEfficiencyTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
@@ -490,7 +490,7 @@ StatusCode BTaggingEfficiencyTool::initialize() {
     ATH_CHECK( m_selectionTool.setProperty("JetAuthor",                    m_jetAuthor) );
     ATH_CHECK( m_selectionTool.setProperty("MinPt",                        m_minPt) );
     ATH_CHECK( m_selectionTool.retrieve() );
-  }
+ }
 
   // if the user decides to ignore these errors, at least make her/him aware of this
   if (m_ignoreOutOfValidityRange) {
@@ -942,6 +942,33 @@ BTaggingEfficiencyTool::listScaleFactorSystematics(bool named) const {
   return uncertainties;
 }
 
+CorrectionCode
+BTaggingEfficiencyTool::getEigenRecompositionCoefficientMap(const std::string &label, std::map<std::string, std::map<std::string, float>> & coefficientMap){
+  // Calling EigenVectorRecomposition method in CDI and retrieve recomposition map.
+  // If success, coefficientMap would be filled and return ok.
+  // If failed, return error.
+  // label  :  flavour label
+  // coefficientMap: store returned coefficient map.
+  if (! m_initialised) {
+    ATH_MSG_ERROR("BTaggingEfficiencyTool has not been initialised");
+    return CorrectionCode::Error;
+  }
+  if(label.compare("B") != 0 &&
+     label.compare("C") != 0 &&
+     label.compare("T") != 0 &&
+     label.compare("Light") != 0){
+    ATH_MSG_ERROR("Flavour label is illegal! Label need to be B,C,T or Light.");
+    return CorrectionCode::Error;
+  }
+  CalibrationStatus status = m_CDI->runEigenVectorRecomposition(m_jetAuthor, label, m_OP);
+  if (status != Analysis::kSuccess){
+    ATH_MSG_ERROR("Failure running EigenVectorRecomposition Method.");
+    return CorrectionCode::Error;
+  }
+  coefficientMap = m_CDI->getEigenVectorRecompositionCoefficientMap();
+  return CorrectionCode::Ok;
+}
+
 // WARNING the behaviour of future calls to getEfficiency and friends are modified by this
 // method - it indicates which systematic shifts are to be applied for all future calls
 SystematicCode BTaggingEfficiencyTool::applySystematicVariation( const SystematicSet & systConfig) {
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEigenVectorRecompositionTool.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEigenVectorRecompositionTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6a80f5835f5f6556443d02d934c860f058a66ce4
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingEigenVectorRecompositionTool.cxx
@@ -0,0 +1,233 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h"
+
+
+BTaggingEigenVectorRecompositionTool::BTaggingEigenVectorRecompositionTool( const std::string & name) : 
+  asg::AsgTool( name )
+{
+  declareProperty("BTaggingEfficiencyTool", m_btageffTool);
+}
+
+BTaggingEigenVectorRecompositionTool::~BTaggingEigenVectorRecompositionTool() 
+{
+
+}
+
+// Initialize BtaggingEfficiencyTool handle and retrieve coefficient map for
+// all flavours. Also initialize vectors which contains all original sources
+// uncertainties' names. One vector for each flavour.
+StatusCode BTaggingEigenVectorRecompositionTool::initialize()
+{
+  ATH_MSG_INFO("Hello BTaggingEigenVectorRecompositionTool user... initializing");
+  ATH_CHECK(m_btageffTool.retrieve());
+
+  if (m_btageffTool.empty()) {
+      ATH_MSG_ERROR("Failed to retrieve BTaggingEfficiencyTool handle");
+      return StatusCode::FAILURE;
+  }
+  CP::CorrectionCode code1 = m_btageffTool->getEigenRecompositionCoefficientMap("B", m_coefficientMapB);
+  CP::CorrectionCode code2 = m_btageffTool->getEigenRecompositionCoefficientMap("C", m_coefficientMapC);
+  CP::CorrectionCode code3 = m_btageffTool->getEigenRecompositionCoefficientMap("T", m_coefficientMapT);
+  CP::CorrectionCode code4 = m_btageffTool->getEigenRecompositionCoefficientMap("Light", m_coefficientMapLight);
+
+  if(code1 != CP::CorrectionCode::Ok) {
+      ATH_MSG_ERROR("Failed to retrieve coefficient map of B");
+      return StatusCode::FAILURE;
+  }
+  if(code2 != CP::CorrectionCode::Ok) {
+      ATH_MSG_ERROR("Failed to retrieve coefficient map of C");
+      return StatusCode::FAILURE;
+  }
+  if(code3 != CP::CorrectionCode::Ok) {
+      ATH_MSG_ERROR("Failed to retrieve coefficient map of T");
+      return StatusCode::FAILURE;
+  }
+  if(code4 != CP::CorrectionCode::Ok) {
+      ATH_MSG_ERROR("Failed to retrieve coefficient map of Light");
+      return StatusCode::FAILURE;
+  }
+  
+  std::map<std::string, std::map<std::string, float>>::iterator outter;
+  
+  outter = m_coefficientMapB.begin();
+  for (std::map<std::string, float>::iterator inner=outter->second.begin();
+       inner!=outter->second.end(); ++inner){
+    m_NPnameListB.push_back(inner->first);
+  }
+  outter = m_coefficientMapC.begin();
+  for (std::map<std::string, float>::iterator inner=outter->second.begin();
+       inner!=outter->second.end(); ++inner){
+    m_NPnameListC.push_back(inner->first);
+  }
+  outter = m_coefficientMapT.begin();
+  for (std::map<std::string, float>::iterator inner=outter->second.begin();
+       inner!=outter->second.end(); ++inner){
+    m_NPnameListT.push_back(inner->first);
+  }
+  outter = m_coefficientMapLight.begin();
+  for (std::map<std::string, float>::iterator inner=outter->second.begin();
+       inner!=outter->second.end(); ++inner){
+    m_NPnameListLight.push_back(inner->first);
+  }
+
+  return StatusCode::SUCCESS;
+
+}
+
+// Return a vector which contains a list of original vector uncertainties names.
+// vector list is for the chosen flavour label. The order of the names is the same
+// as the coefficient values given by getCoefficients()
+std::vector<std::string> BTaggingEigenVectorRecompositionTool::getListOfOriginalNuisanceParameters(const std::string & label) const
+{
+  ATH_MSG_INFO("getListOfOriginalNuisanceParameters()");
+  
+  std::vector<std::string> dummy;
+  if(label.compare("B") == 0)
+    return m_NPnameListB;
+  else if(label.compare("C") == 0)
+    return m_NPnameListC;
+  else if(label.compare("T") == 0)
+    return m_NPnameListT;
+  else if(label.compare("Light") == 0)
+    return m_NPnameListLight;
+  else{
+    ATH_MSG_ERROR("Label is illegal! Available label: B, C, T and Light.");    
+    return dummy;
+  }
+
+  return dummy;
+}
+
+// Produce a coefficient map contains only eigenvectors that is showing in
+// eigenIdxList and return it to user. If given empty evIdxList, the function
+// returns a full map. Produced map is for the chosen flavour label.
+std::map<std::string, std::map<std::string, float>> BTaggingEigenVectorRecompositionTool::getCoefficientMap(const std::string & label, const std::vector<unsigned int> evIdxList) const
+{
+  ATH_MSG_INFO("getCoefficientMap()");
+  
+  std::map<std::string, std::map<std::string, float>> fullMap;
+  if(label.compare("B") == 0)
+    fullMap = m_coefficientMapB;
+  else if(label.compare("C") == 0)
+    fullMap = m_coefficientMapC;
+  else if(label.compare("T") == 0)
+    fullMap = m_coefficientMapT;
+  else if(label.compare("Light") == 0)
+    fullMap = m_coefficientMapLight;
+  else{
+    ATH_MSG_ERROR("Label is illegal! Available label: B, C, T and Light.");    
+    return fullMap;
+  }
+  
+  std::vector<std::string> evNameList;
+  for(unsigned int i : evIdxList){
+    // Note: This eigenvector name convention has to be same with that in CalibrationDataEigenVariations. One way to avoid the naming convention is to change coefficient map structure into: map<unsigned int, map<string, float>>
+    evNameList.push_back("Eigen_"+label+"_"+std::to_string(i));
+  }
+
+  std::map<std::string, std::map<std::string, float>> resultMap;
+  for (std::map<std::string, std::map<std::string, float>>::iterator iter = fullMap.begin();
+       iter != fullMap.end(); ++iter){
+    if (evNameList.end() != std::find(evNameList.begin(), evNameList.end(), iter->first) ||
+	evNameList.empty())
+      resultMap[iter->first] = iter->second;
+  }
+  return resultMap;
+}
+
+// Returns a vector contains the coefficients value of the chosen label
+// and the chosen eigenvector. The order of the value is the same as
+// the order of original uncertainty names given by
+// getListOfOriginalNuisanceParameters()
+std::vector<float> BTaggingEigenVectorRecompositionTool::getCoefficients(const std::string & label, const unsigned int evIdx) const
+{
+  ATH_MSG_INFO("getCoefficients()");
+  std::vector<float> coefficients; // dummy to be replaced
+  std::map<std::string, std::map<std::string, float>> fullMap;
+  std::vector<std::string> NPnameList;
+  if(label.compare("B") == 0){
+    fullMap = m_coefficientMapB;
+    NPnameList = m_NPnameListB;
+  }
+  else if(label.compare("C") == 0){
+    fullMap = m_coefficientMapC;
+    NPnameList = m_NPnameListC;
+  }
+  else if(label.compare("T") == 0){
+    fullMap = m_coefficientMapT;
+    NPnameList = m_NPnameListT;
+  }
+  else if(label.compare("Light") == 0){
+    fullMap = m_coefficientMapLight;
+    NPnameList = m_NPnameListLight;
+  }
+  else{
+    ATH_MSG_ERROR("Label is illegal! Available label: B, C, T and Light.");    
+    return coefficients;
+  }
+
+  std::string evName = "Eigen_"+label+"_"+std::to_string(evIdx);
+  if(fullMap.count(evName) <= 0){
+    ATH_MSG_ERROR("Cannot find " << evName <<" in Eigen Vector coefficient map.");
+    return coefficients;
+  }
+  
+  std::map<std::string, float> oneEVmap = fullMap[evName];
+  for(std::string NPname : NPnameList){
+    coefficients.push_back(oneEVmap[NPname]);
+  }
+  return coefficients;
+}
+
+// Return number of eigenvectors used for the chosen label.
+int BTaggingEigenVectorRecompositionTool::getNumEigenVectors(const std::string & label)const{
+  std::map<std::string, std::map<std::string, float>> fullMap;
+  if(label.compare("B") == 0)
+    fullMap = m_coefficientMapB;
+  else if(label.compare("C") == 0)
+    fullMap = m_coefficientMapC;
+  else if(label.compare("T") == 0)
+    fullMap = m_coefficientMapT;
+  else if(label.compare("Light") == 0)
+    fullMap = m_coefficientMapLight;
+  else{
+    ATH_MSG_ERROR("Label is illegal! Available label: B, C, T and Light.");    
+    return -1;
+  }
+  return fullMap.size();
+}
+
+// this returns a list of eigen vector systematics supported by the btaggingEfficiency tool handle
+CP::SystematicSet BTaggingEigenVectorRecompositionTool::affectingSystematics() const {
+  return m_btageffTool->affectingSystematics();
+}
+
+// it indicates which systematic shifts are to be applied for all future calls
+// no systematics for now, proxy for later
+CP::SystematicCode BTaggingEigenVectorRecompositionTool::applySystematicVariation( const CP::SystematicSet & systConfig )
+{
+  for (auto syst : systConfig) {
+    CP::SystematicSet myset;
+    ATH_MSG_WARNING("applySystematicVariation was called for " << syst.name() << " but BTaggingEigenVectorRecompositionTool does not apply Systematic Variations");
+    //the truth tagging tool provides results for all possible systematic variations in its results objects, the user does not need to call each one seperatly.
+  }
+  return CP::SystematicCode::Ok;
+}
+
+// returns true if the argument systematic is supported by the
+// btaggingEfficiency tool handle
+bool BTaggingEigenVectorRecompositionTool::isAffectedBySystematic( const CP::SystematicVariation & systematic ) const
+{
+  CP::SystematicSet sys = affectingSystematics();
+  return sys.find(systematic) != sys.end();
+}
+
+// subset of Eigenvector systeamtics that are recommended by the
+// btaggingEfficiency tool handle
+CP::SystematicSet BTaggingEigenVectorRecompositionTool::recommendedSystematics() const {
+  return affectingSystematics();
+}
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingSelectionTool.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingSelectionTool.cxx
index 6d4310cbb62a0696a2812c75e663f9df4f7855d2..d6fecd87342ec32d0d51455ab1b27efb3e77aafc 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingSelectionTool.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingSelectionTool.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"
@@ -195,6 +195,7 @@ void BTaggingSelectionTool::ExtractTaggerProperties(taggerproperties &tagger, st
   }
 }
 
+
 CorrectionCode BTaggingSelectionTool::getTaggerWeight( const xAOD::Jet& jet, double & tagweight, bool useVetoWP) const{
 
   taggerproperties localtagger;
@@ -238,7 +239,7 @@ CorrectionCode BTaggingSelectionTool::getTaggerWeight( const xAOD::Jet& jet, dou
     return  CorrectionCode::Ok;
   }
 
-  else if(taggerName.find("DL1") != string::npos){
+ else if(taggerName.find("DL1") != string::npos){
 
   double dl1_pb(-10.);
   double dl1_pc(-10.);
@@ -296,7 +297,7 @@ CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, dou
   tagweight = -100.;
   if( taggerName.find("DL1") != string::npos ){
 
-    bool valid_input = (!std::isnan(pu) && pb>0 && pc>0 && pu>0);
+    bool valid_input = (!std::isnan(pu) && pb>=0 && pc>=0 && pu>=0);
 
     if (!valid_input){
       if(m_ErrorOnTagWeightFailure){
@@ -309,9 +310,10 @@ CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, dou
     }
 
     if(OP.find("CTag") != string::npos){
-     tagweight = log( pc/(localtagger.fraction*pb+(1.-localtagger.fraction)*pu) );
-    }else{
-     tagweight = log( pb/(localtagger.fraction*pc+(1.-localtagger.fraction)*pu) );
+     tagweight = log(pc / (localtagger.fraction * pb + (1. - localtagger.fraction) * pu));
+    }
+    else{
+     tagweight = log(pb / (localtagger.fraction * pc + (1. - localtagger.fraction) * pu) );
     }
 
     return CorrectionCode::Ok;
@@ -326,20 +328,18 @@ CorrectionCode BTaggingSelectionTool::getTaggerWeight( double pb, double pc, dou
 
 
 asg::AcceptData BTaggingSelectionTool::accept( const xAOD::IParticle* p ) const {
-  // Reset the result:
-  asg::AcceptData acceptData(&m_acceptinfo);
 
   // Check if this is a jet:
   if( p->type() != xAOD::Type::Jet ) {
     ATH_MSG_ERROR( "accept(...) Function received a non-jet" );
-    return acceptData;
+    return asg::AcceptData (&m_acceptinfo);
   }
 
   // Cast it to a jet:
   const xAOD::Jet* jet = dynamic_cast< const xAOD::Jet* >( p );
   if( ! jet ) {
     ATH_MSG_FATAL( "accept(...) Failed to cast particle to jet" );
-    return acceptData;
+    return asg::AcceptData (&m_acceptinfo);
   }
 
   // Let the specific function do the work:
@@ -347,7 +347,7 @@ asg::AcceptData BTaggingSelectionTool::accept( const xAOD::IParticle* p ) const
 }
 
 asg::AcceptData BTaggingSelectionTool::accept( const xAOD::Jet& jet ) const {
-  asg::AcceptData acceptData(&m_acceptinfo);
+  asg::AcceptData acceptData (&m_acceptinfo);
 
   if (! m_initialised) {
     ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
@@ -375,7 +375,6 @@ asg::AcceptData BTaggingSelectionTool::accept( const xAOD::Jet& jet ) const {
     double weight_mv2cl100(-10.);
     const xAOD::BTagging* btag = xAOD::BTaggingUtilities::getBTagging( jet );
 
-
     if ((!btag)){
       ATH_MSG_ERROR("Failed to retrieve the BTagging information");
     }
@@ -421,7 +420,8 @@ asg::AcceptData BTaggingSelectionTool::accept( const xAOD::Jet& jet ) const {
 
 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double tag_weight) const
 {
-  asg::AcceptData acceptData(&m_acceptinfo);
+  
+  asg::AcceptData acceptData (&m_acceptinfo);
 
   if (! m_initialised) {
     ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
@@ -430,7 +430,7 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double tag_
 
   eta = std::fabs(eta);
 
-  if (! checkRange(pT, eta, acceptData))
+  if (! checkRange(pT, eta,acceptData))
     return acceptData;
 
   // After initialization, either m_tagger.spline or m_tagger.constcut should be non-zero
@@ -443,8 +443,8 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double tag_
   if (  tag_weight < cutvalue ){
     return acceptData;
   }
+  
   acceptData.setCutResult( "WorkingPoint", true );
-
   // Return the result:
   return acceptData;
 }
@@ -453,7 +453,7 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double tag_
 
 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double weight_mv2cl100, double weight_mv2c100) const
 {
-  asg::AcceptData acceptData(&m_acceptinfo);
+   asg::AcceptData acceptData (&m_acceptinfo);
 
   if (! m_initialised) {
     ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
@@ -462,7 +462,7 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double weig
 
   eta = std::fabs(eta);
 
-  if (! checkRange(pT, eta, acceptData))
+  if (! checkRange(pT, eta,acceptData))
     return acceptData;
 
   // After initialization, either m_tagger.spline or m_tagger.constcut should be non-zero
@@ -511,7 +511,7 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double weig
 
 asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double pb, double pc, double pu) const
  {
-   asg::AcceptData acceptData(&m_acceptinfo);
+   asg::AcceptData acceptData (&m_acceptinfo);
 
    if (! m_initialised) {
      ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
@@ -520,7 +520,7 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double pb,
 
    eta = std::fabs(eta);
 
-   if (! checkRange(pT, eta, acceptData))
+   if (! checkRange(pT, eta,acceptData))
      return acceptData;
 
    // After initialization, either m_tagger.spline or m_tagger.constcut should be non-zero
@@ -550,6 +550,8 @@ asg::AcceptData BTaggingSelectionTool::accept(double pT, double eta, double pb,
 
 int BTaggingSelectionTool::getQuantile( const xAOD::IParticle* p ) const {
   // Check if this is a jet:
+
+
   if( p->type() != xAOD::Type::Jet ) {
     ATH_MSG_ERROR( "accept(...) Function received a non-jet" );
     return -1;
@@ -581,7 +583,7 @@ int BTaggingSelectionTool::getQuantile( const xAOD::Jet& jet ) const{
 }
 
 
-int BTaggingSelectionTool::getQuantile(double pT, double eta, double weight_mv2) const
+int BTaggingSelectionTool::getQuantile(double pT, double eta, double weight_mv2 ) const
 {
   if (! m_initialised) {
     ATH_MSG_ERROR("BTaggingSelectionTool has not been initialised");
@@ -593,29 +595,28 @@ int BTaggingSelectionTool::getQuantile(double pT, double eta, double weight_mv2)
   // returns 3 if between 77% and 70%
   // returns 2 if between 85% and 77%
   // returns 1 if between 100% and 85%
-  // returns 0 if smaller than -1e4-> should never happen
-  // return -1 if bigger than 1e4 or not in b-tagging acceptance
+  // return -1 not in b-tagging acceptance
   //////////////////////
 
   int bin_index(-1);
-
-  asg::AcceptData acceptData(&m_acceptinfo);
-  if (! checkRange(pT, eta, acceptData)) return bin_index;
+  asg::AcceptData acceptData (&m_acceptinfo);
+  if (! checkRange(pT, eta,acceptData)) return bin_index;
 
   // If in b-tagging acceptance, cont.tagging
-  for (int i=0; i<=5; ++i) {
+  for (int i=1; i<=5; ++i) {
     if (weight_mv2 < m_continuouscuts[i]) {
       bin_index = i;
       break;
     }
+    else if (weight_mv2 >= m_continuouscuts[5]){
+      bin_index = 5;
+      break;
+    }
   }
-
-  if (0==bin_index) ATH_MSG_ERROR("B-tagging weight is smaller than 1e-4, this shouldn't happen!");
-
   return bin_index;
 }
 
-bool BTaggingSelectionTool::checkRange(double pT, double eta, asg::AcceptData& acceptData) const
+bool BTaggingSelectionTool::checkRange(double pT, double eta,asg::AcceptData& acceptData) const
 {
   // Do the |eta| cut:
   if( eta > m_maxEta ) {
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingTruthTaggingTool.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingTruthTaggingTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..584461fa8c6955215701b52c4d8dc344e1fcd0fd
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/BTaggingTruthTaggingTool.cxx
@@ -0,0 +1,1310 @@
+#include "xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h"
+#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
+#include "xAODBTagging/BTagging.h"
+#include "xAODBTagging/BTaggingUtilities.h"
+#include "CalibrationDataInterface/CalibrationDataInterfaceROOT.h"
+#include "CalibrationDataInterface/CalibrationDataContainer.h"
+#include "PATInterfaces/SystematicRegistry.h"
+#include "PathResolver/PathResolver.h"
+#include "PATCore/AcceptData.h"
+
+#include "TFile.h"
+
+#include <algorithm>
+#include <numeric>
+
+using std::string;
+
+using CP::CorrectionCode;
+using CP::SystematicSet;
+using CP::SystematicVariation;
+using CP::SystematicCode;
+using CP::SystematicRegistry;
+
+using Analysis::Uncertainty;
+using Analysis::CalibrationDataVariables;
+using Analysis::CalibrationDataContainer;
+using Analysis::CalibResult;
+using Analysis::CalibrationStatus;
+using Analysis::Total;
+using Analysis::SFEigen;
+using Analysis::SFNamed;
+using Analysis::None;
+
+using xAOD::IParticle;
+
+
+BTaggingTruthTaggingTool::BTaggingTruthTaggingTool( const std::string & name)
+  : asg::AsgTool( name ),
+    m_effTool ("BTaggingEfficiencyTool/effTool", this),
+    m_selTool ("BTaggingSelectionTool/selTool", this)
+  {
+
+  m_initialised = false;
+
+
+  // properties of BTaggingTruthTaggingTool
+  declareProperty( "IgnoreScaleFactors", m_ignoreSF=true, "ignore scale factors in computation of TRF weight");
+  declareProperty( "UsePermutations", m_usePerm=true, "if the chosen permutation is used, a reweighting is applied to the TRF weight for systematics");
+  declareProperty( "UseQuantile", m_useQuntile=true, "if the chosen quantile is used, a reweighting is applied to the TRF weight for systematics");
+  declareProperty( "UseSystematics", m_useSys=false, "will the results contain all systematic variations, or just the nominal");
+  declareProperty( "MaxNtagged", m_nbtag=2, "what is the maximal possible number of tagged jets");
+
+  // properties of BtaggingSelectionTool
+  declareProperty( "MaxEta", m_maxEta = 2.5 );
+  declareProperty( "MinPt", m_minPt = 20000 /*MeV*/);
+  declareProperty( "MaxRangePt", m_maxRangePt = 1000000 /*MeV*/);
+
+  // properties of BTaggingEfficiencyTool
+  declareProperty("TaggerName",                      m_taggerName="MV2c10",            "tagging algorithm name as specified in CDI file");
+  declareProperty("OperatingPoint",                  m_OP="FixedCutBEff_77",                    "operating point as specified in CDI file");
+  declareProperty("JetAuthor",                       m_jetAuthor="AntiKt4EMTopoJets",             "jet collection & JVF/JVT specification in CDI file");
+  declareProperty("ScaleFactorFileName",             m_SFFile = "xAODBTaggingEfficiency/13TeV/2016-20_7-13TeV-MC15-CDI-July12_v1.root",              "name of the official scale factor calibration CDI file (uses PathResolver)");
+  declareProperty("UseDevelopmentFile",              m_useDevFile = false,       "specify whether or not to use the (PathResolver) area for temporary scale factor calibration CDI files");
+  declareProperty("EfficiencyFileName",              m_EffFile = "",             "name of optional user-provided MC efficiency CDI file");
+  declareProperty("ScaleFactorBCalibration",         m_SFBName = "default",      "name of b-jet scale factor calibration object");
+  declareProperty("ScaleFactorCCalibration",         m_SFCName = "default",      "name of c-jet scale factor calibration object");
+  declareProperty("ScaleFactorTCalibration",         m_SFTName = "default",      "name of tau-jet scale factor calibration object");
+  declareProperty("ScaleFactorLightCalibration",     m_SFLightName = "default",  "name of light-flavour jet scale factor calibration object");
+  declareProperty("EigenvectorReductionB",           m_EVReductionB = "Loose",   "b-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
+  declareProperty("EigenvectorReductionC",           m_EVReductionC = "Loose",   "c-jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
+  declareProperty("EigenvectorReductionLight",       m_EVReductionLight = "Loose","light-flavour jet scale factor Eigenvector reduction strategy; choose between 'Loose', 'Medium', 'Tight'");
+  declareProperty("EfficiencyBCalibrations",         m_EffBName = "default",     "(semicolon-separated) name(s) of b-jet efficiency object(s)");
+  declareProperty("EfficiencyCCalibrations",         m_EffCName = "default",     "(semicolon-separated) name(s) of c-jet efficiency object(s)");
+  declareProperty("EfficiencyTCalibrations",         m_EffTName = "default",     "(semicolon-separated) name(s) of tau-jet efficiency object(s)");
+  declareProperty("EfficiencyLightCalibrations",     m_EffLightName = "default", "(semicolon-separated) name(s) of light-flavour-jet efficiency object(s)");
+  declareProperty("ExcludeFromEigenVectorTreatment", m_excludeFromEV = "",       "(semicolon-separated) names of uncertainties to be excluded from eigenvector decomposition (if used)");
+  declareProperty("SystematicsStrategy",             m_systStrategy = "SFEigen", "name of systematics model; presently choose between 'SFEigen' and 'Envelope'");
+  declareProperty("ConeFlavourLabel",                m_coneFlavourLabel = true, "specify whether or not to use the cone-based flavour labelling instead of the default ghost association based labelling");
+  declareProperty("OldConeFlavourLabel",             m_oldConeFlavourLabel = false, "when using cone-based flavour labelling, specify whether or not to use the (deprecated) Run-1 legacy labelling");
+  declareProperty("CutBenchmark",                    m_cutBenchmark = "FixedCutBEff_70", "if you want to run in continuous you need to fix a benchmark - it does something only if running in Continuous OP");
+  declareProperty("ExcludeSpecificEigens",            m_excludeEV = "" ,    "(semicolon-separated) names of Eigens you want to exclude. in case of continuous some eigenvectors can be ignored to make the computation faster");
+  declareProperty("StoreOnlyUpVariations",            m_doOnlyUpVariations = false ,    "If set to true it processes only the __1up b-tagging variations. It speeds up the computation in case of symmetric variations.");
+  declareProperty("doDirectTagging",                  m_doDirectTag = false ,    "If set to true it also computes and stores the direct tagging choice and the related SFs for each jet"); 
+}
+
+StatusCode BTaggingTruthTaggingTool::setEffMapIndex(const std::string& flavour, unsigned int index){
+    ANA_CHECK_SET_TYPE (StatusCode);
+
+    ANA_CHECK(m_effTool->setMapIndex(flavour, index));
+    if(m_useQuntile && !m_continuous){
+      for(unsigned int iop=0; iop<m_availableOP.size(); iop++){
+          ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)]->setMapIndex(flavour, index));
+      }
+    }
+    return  StatusCode::SUCCESS;
+}
+
+void BTaggingTruthTaggingTool::setUseSystematics(bool useSystematics){
+  ATH_MSG_DEBUG("setting the use of systematics to: " <<useSystematics);
+  m_useSys = useSystematics;
+  ATH_MSG_DEBUG(" m_useSys = " << m_useSys);
+}
+
+SystematicSet BTaggingTruthTaggingTool::affectingSystematics() const {
+  return m_effTool->affectingSystematics();
+}
+
+SystematicCode BTaggingTruthTaggingTool::applySystematicVariation( const CP::SystematicSet & systConfig )
+{
+    for (auto syst : systConfig) {
+        CP::SystematicSet myset;
+        ATH_MSG_WARNING("applySystematicVariation was called for " << syst.name() << " but BTaggingTruthTaggingTool does not apply Systematic Variations");
+        //the truth tagging tool provides results for all possible systematic variations in its results objects, the user does not need to call each one seperatly.
+    }
+   return SystematicCode::Ok;
+}
+
+bool BTaggingTruthTaggingTool::isAffectedBySystematic( const CP::SystematicVariation & systematic ) const
+{
+  SystematicSet sys = affectingSystematics();
+  return sys.find( systematic) != sys.end();
+}
+
+SystematicSet BTaggingTruthTaggingTool::recommendedSystematics() const {
+  return affectingSystematics();
+}
+
+StatusCode BTaggingTruthTaggingTool::initialize() {
+
+  ANA_CHECK_SET_TYPE (StatusCode);
+
+  m_initialised = true;
+
+  ANA_CHECK(m_selTool.setProperty("MaxEta",  m_maxEta));
+  ANA_CHECK(m_selTool.setProperty("MaxRangePt",  m_maxRangePt));
+  ANA_CHECK(m_selTool.setProperty("MinPt",  m_minPt));
+  ANA_CHECK(m_selTool.setProperty("TaggerName",  m_taggerName));
+  ANA_CHECK(m_selTool.setProperty("OperatingPoint", m_OP));
+  ANA_CHECK(m_selTool.setProperty("JetAuthor", m_jetAuthor));
+  ANA_CHECK(m_selTool.setProperty("FlvTagCutDefinitionsFileName", m_SFFile));
+  ANA_CHECK(m_selTool.initialize());
+
+  ANA_CHECK(m_effTool.setProperty("MinPt",                           m_minPt));
+  ANA_CHECK(m_effTool.setProperty("TaggerName",                      m_taggerName));
+  ANA_CHECK(m_effTool.setProperty("OperatingPoint",                  m_OP));
+  ANA_CHECK(m_effTool.setProperty("JetAuthor",                       m_jetAuthor));
+  ANA_CHECK(m_effTool.setProperty("ScaleFactorFileName",             m_SFFile ));
+  ANA_CHECK(m_effTool.setProperty("UseDevelopmentFile",              m_useDevFile ));
+  ANA_CHECK(m_effTool.setProperty("EfficiencyFileName",              m_EffFile ));
+  ANA_CHECK(m_effTool.setProperty("ScaleFactorBCalibration",         m_SFBName ));
+  ANA_CHECK(m_effTool.setProperty("ScaleFactorCCalibration",         m_SFCName ));
+  ANA_CHECK(m_effTool.setProperty("ScaleFactorTCalibration",         m_SFTName ));
+  ANA_CHECK(m_effTool.setProperty("ScaleFactorLightCalibration",     m_SFLightName ));
+  ANA_CHECK(m_effTool.setProperty("EigenvectorReductionB",           m_EVReductionB ));
+  ANA_CHECK(m_effTool.setProperty("EigenvectorReductionC",           m_EVReductionC ));
+  ANA_CHECK(m_effTool.setProperty("EigenvectorReductionLight",       m_EVReductionLight ));
+  ANA_CHECK(m_effTool.setProperty("EfficiencyBCalibrations",         m_EffBName ));
+  ANA_CHECK(m_effTool.setProperty("EfficiencyCCalibrations",         m_EffCName ));
+  ANA_CHECK(m_effTool.setProperty("EfficiencyTCalibrations",         m_EffTName ));
+  ANA_CHECK(m_effTool.setProperty("EfficiencyLightCalibrations",     m_EffLightName ));
+  ANA_CHECK(m_effTool.setProperty("ExcludeFromEigenVectorTreatment", m_excludeFromEV ));
+  ANA_CHECK(m_effTool.setProperty("SystematicsStrategy",             m_systStrategy ));
+  ANA_CHECK(m_effTool.setProperty("ConeFlavourLabel",                m_coneFlavourLabel ));
+  ANA_CHECK(m_effTool.setProperty("OldConeFlavourLabel",          m_oldConeFlavourLabel ));
+
+  ANA_CHECK(m_effTool.initialize());
+
+  m_continuous = false;
+
+  if(m_OP.find("FlatBEff") != std::string::npos){
+    m_availableOP.resize(m_availableOP_fixEff.size());
+    m_availableOP=m_availableOP_fixEff;
+  }
+  else if(m_OP.find("FixedCutBEff") != std::string::npos){
+    m_availableOP.resize(m_availableOP_fixCut.size());
+    m_availableOP=m_availableOP_fixCut;
+  }
+  else if(m_OP.find("Continuous") != std::string::npos){
+    ATH_MSG_INFO("You are running in Continuous and you choosed " << m_cutBenchmark <<" as benchmark" );
+    m_continuous = true;
+    m_availableOP.resize(m_availableOP_fixCut.size());
+    m_availableOP=m_availableOP_fixCut;
+  }
+  else if(m_useQuntile){
+    ATH_MSG_ERROR(m_OP << " not in the list of available OPs");
+    return StatusCode::FAILURE;
+  }
+
+  if(m_continuous){
+    m_OperatingPoint_index = find(m_availableOP.begin(), m_availableOP.end(), m_cutBenchmark) - m_availableOP.begin();
+  }
+  else{
+    if(m_useQuntile){
+      m_OperatingPoint_index = find(m_availableOP.begin(), m_availableOP.end(), m_OP) - m_availableOP.begin();
+      if(m_OperatingPoint_index >= m_availableOP.size()) {
+	ATH_MSG_ERROR(m_OP << " not in the list of available OPs");
+	return StatusCode::FAILURE;
+      }
+    }
+  }
+  
+  m_eff_syst.clear();
+  m_sys_name.clear();
+  CP::SystematicSet def_set;
+  m_eff_syst.push_back(def_set);
+  m_sys_name.push_back("Nominal");
+
+  if(m_useSys){
+    std::vector<std::string> excludeEV_vector;
+    if(m_excludeEV != "")
+      excludeEV_vector = split(m_excludeEV, ';');
+    CP::SystematicSet systs = m_effTool->affectingSystematics();
+    for (const auto & syst : systs) {
+      CP::SystematicSet myset;
+      string s = syst.name();
+      if(m_doOnlyUpVariations && s.find("__1down") !=string::npos) continue;
+      if(std::any_of(excludeEV_vector.begin(), excludeEV_vector.end(), [&s](const std::string& str) { return str.find(s) != std::string::npos; })) continue;
+  
+      myset.insert(syst);
+      if(m_excludeEV != "")
+	ATH_MSG_INFO("Adding systematic " << syst.name() << "to the list ");
+      else
+	ATH_MSG_DEBUG("Adding systematic " << syst.name() << "to the list ");
+      m_eff_syst.push_back(myset);
+      m_sys_name.push_back(syst.name());
+    }
+  }
+  if(m_useQuntile == true || m_continuous == true){
+    ATH_MSG_INFO("m_useQuntile true");
+
+    //open the CDI file to get the cutvalues for all working points.
+    TString pathtofile =  PathResolverFindCalibFile(m_SFFile);
+    m_inf = TFile::Open(pathtofile, "read");
+    m_binEdges.clear();
+
+    for(unsigned int iop=0; iop<m_availableOP.size(); iop++){
+
+      if(!m_continuous){
+	std::string toolname = name()+"_eff_"+m_availableOP.at(iop);
+	
+	m_effTool_allOP[m_availableOP.at(iop)] = asg::AnaToolHandle<IBTaggingEfficiencyTool>("BTaggingEfficiencyTool/"+toolname,this);
+	
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("OperatingPoint", m_availableOP.at(iop)));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("TaggerName",                      m_taggerName));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("JetAuthor",                       m_jetAuthor));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ScaleFactorFileName",             m_SFFile ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("UseDevelopmentFile",              m_useDevFile ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EfficiencyFileName",              m_EffFile ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ScaleFactorBCalibration",         m_SFBName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ScaleFactorCCalibration",         m_SFCName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ScaleFactorTCalibration",         m_SFTName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ScaleFactorLightCalibration",     m_SFLightName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EigenvectorReductionB",           m_EVReductionB ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EigenvectorReductionC",           m_EVReductionC ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EigenvectorReductionLight",       m_EVReductionLight ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EfficiencyBCalibrations",         m_EffBName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EfficiencyCCalibrations",         m_EffCName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EfficiencyTCalibrations",         m_EffTName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("EfficiencyLightCalibrations",     m_EffLightName ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ExcludeFromEigenVectorTreatment", m_excludeFromEV ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("SystematicsStrategy",             m_systStrategy ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("ConeFlavourLabel",                m_coneFlavourLabel ));
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].setProperty("OldConeFlavourLabel",          m_oldConeFlavourLabel ));
+	
+	ANA_CHECK(m_effTool_allOP[m_availableOP.at(iop)].initialize());
+	
+	if(m_OP.find("FixedCutBEff")!= std::string::npos){
+	  TString cutname = m_taggerName+"/"+m_jetAuthor+"/"+m_availableOP.at(iop)+"/cutvalue";
+	  float cutval = ((TVector*) m_inf->Get(cutname))[0](0);
+	  m_binEdges.push_back(cutval);
+	} //FCBEff
+      } //!Continuous
+
+      else{
+	if(m_cutBenchmark.find("FixedCutBEff")!= std::string::npos){
+          TString cutname = m_taggerName+"/"+m_jetAuthor+"/"+m_availableOP.at(iop)+"/cutvalue";
+          float cutval = ((TVector*) m_inf->Get(cutname))[0](0);
+          m_binEdges.push_back(cutval);
+	} //FCBEff
+      } //Continuous
+    } //loop
+  } //quantile
+
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::setJets(TRFinfo &trfinf,std::vector<double>& pt, std::vector<double>& eta, std::vector<int>& flav, std::vector<double>& tagw){
+  ANA_CHECK_SET_TYPE (StatusCode);
+  if(pt.size()!=eta.size() || pt.size()!=flav.size() || pt.size()!=tagw.size()){
+    ATH_MSG_ERROR( "Vectors of pt, eta, flav and tagw should have same size" );
+    return StatusCode::FAILURE;
+  }
+
+  std::vector<Analysis::CalibrationDataVariables>* vars = new std::vector<Analysis::CalibrationDataVariables>(0);
+  for(unsigned int i =0; i<pt.size(); i++){
+    Analysis::CalibrationDataVariables vars_appo;
+    if (!fillVariables(pt.at(i), eta.at(i), tagw.at(i), vars_appo)){
+      ATH_MSG_ERROR("unable to fill variables");
+      return StatusCode::FAILURE;
+    }
+    vars->push_back(vars_appo);
+  }
+
+  ANA_CHECK(setJets(trfinf,flav, vars));
+  delete vars;
+  return StatusCode::SUCCESS;
+}
+
+StatusCode BTaggingTruthTaggingTool::setJets(TRFinfo &trfinf,const xAOD::JetContainer& jets){
+  ANA_CHECK_SET_TYPE (StatusCode);
+  std::vector<int> flav;
+  std::vector<Analysis::CalibrationDataVariables>* vars = new std::vector<Analysis::CalibrationDataVariables>(0);
+  for(const auto jet : jets) {
+    Analysis::CalibrationDataVariables vars_appo;
+    if (!fillVariables(*jet, vars_appo)){
+      ATH_MSG_ERROR("unable to fill variables");
+      return StatusCode::FAILURE;
+    }
+
+    vars->push_back(vars_appo);
+    flav.push_back(jetFlavourLabel(*jet));
+  }
+
+  ANA_CHECK(setJets(trfinf,flav, vars));
+  delete vars;
+  flav.clear();
+  return StatusCode::SUCCESS;
+}
+
+StatusCode BTaggingTruthTaggingTool::setJets(TRFinfo &trfinf,std::vector<int>& flav, std::vector<Analysis::CalibrationDataVariables>* vars){
+  if(flav.size()!=vars->size()){
+    ATH_MSG_ERROR( "Vector of CalibrationDataVariables and flavour should have same size" );
+    return StatusCode::FAILURE;
+  }
+  trfinf.jets.clear();
+  for(unsigned int i =0; i<vars->size(); i++){
+    jetVariable jetVar_appo;
+    jetVar_appo.flav=flav.at(i);
+    jetVar_appo.vars=vars->at(i);
+    trfinf.jets.push_back(jetVar_appo);
+
+  }
+  trfinf.njets=trfinf.jets.size();
+  return StatusCode::SUCCESS;
+}
+
+
+
+bool BTaggingTruthTaggingTool::fillVariables( const xAOD::Jet& jet, CalibrationDataVariables& x){
+  x.jetPt = jet.pt();
+  x.jetEta = jet.eta();
+  x.jetTagWeight = 0.;
+  x.jetAuthor = m_jetAuthor;
+
+  const xAOD::BTagging* tagInfo = xAOD::BTaggingUtilities::getBTagging( jet );
+  if (!tagInfo) return false;
+
+  return tagInfo->MVx_discriminant(m_taggerName, x.jetTagWeight);
+  delete tagInfo;
+
+}
+
+bool BTaggingTruthTaggingTool::fillVariables( const double jetPt, const double jetEta, const double jetTagWeight, CalibrationDataVariables& x){
+  x.jetPt = jetPt;
+  x.jetEta = jetEta;
+  x.jetTagWeight = jetTagWeight;
+  x.jetAuthor = m_jetAuthor;
+  return true;
+}
+
+double BTaggingTruthTaggingTool::getPermutationRW(TRFinfo &trfinf,bool isIncl, unsigned int nbtag, int sys){
+  double w = 1.;
+  if(nbtag < trfinf.njets && ((!isIncl && trfinf.permprob_ex.at(nbtag) == 0.) || (isIncl && trfinf.permprob_in.at(nbtag) == 0.)) )  {
+    ATH_MSG_ERROR("Permutations need to be chosen before computing reweighting");
+  }
+  if(nbtag > trfinf.njets) return 1.;
+  if(isIncl) {
+    w = trfWeight(trfinf,trfinf.perm_in.at(nbtag));
+    return w/trfinf.trfwsys_in[sys].at(nbtag)/trfinf.permprob_in.at(nbtag);
+  }
+  else {
+    w = trfWeight(trfinf,trfinf.perm_ex.at(nbtag));
+    return w/trfinf.trfwsys_ex[sys].at(nbtag)/trfinf.permprob_ex.at(nbtag);
+  }
+}
+
+
+
+StatusCode BTaggingTruthTaggingTool::GetTruthTagWeights(TRFinfo &trfinf, std::vector<double> &trf_weight_ex, std::vector<double> &trf_weight_in, int sys){
+
+  ANA_CHECK_SET_TYPE (StatusCode);
+
+  if(sys==0) ANA_CHECK(getAllEffMC(trfinf));
+  ANA_CHECK(check_syst_range(sys));
+  if(trfinf.trfwsys_ex.size()==0)  trfinf.trfwsys_ex.resize(m_eff_syst.size());
+  if(trfinf.trfwsys_in.size()==0) trfinf.trfwsys_in.resize(m_eff_syst.size());
+
+  ANA_CHECK(getAllEffSF(trfinf,sys));
+  ANA_CHECK(getTRFweight(trfinf,m_nbtag, true, sys));
+
+  if(sys==0){ // don't need permutation or tag bin reweighting
+    if(m_usePerm){
+      // choice of the selected permutation
+      ANA_CHECK(chooseAllTagPermutation(trfinf,m_nbtag));
+    }
+    if(m_useQuntile) {
+      // choice of the tagged bins
+      ANA_CHECK(chooseAllTagBins(trfinf));
+    }
+  }
+  else {
+    if(m_usePerm) {
+      for(unsigned int ib = 0; ib < trfinf.trfwsys_ex[sys].size(); ib++) {
+        trfinf.trfwsys_ex[sys].at(ib) *= getPermutationRW(trfinf,false, ib, sys);
+        trfinf.trfwsys_in[sys].at(ib) *= getPermutationRW(trfinf,true, ib, sys);
+        if(m_useQuntile) {
+	  trfinf.trfwsys_ex[sys].at(ib) *= getTagBinsRW(trfinf,false, ib);
+	  trfinf.trfwsys_in[sys].at(ib) *= getTagBinsRW(trfinf,true, ib);
+        }
+      }
+    }
+  }
+  trf_weight_ex = trfinf.trfwsys_ex[sys];
+  trf_weight_in = trfinf.trfwsys_in[sys];
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::CalculateResults(TRFinfo &trfinf,Analysis::TruthTagResults& results,int rand_seed){
+  ANA_CHECK_SET_TYPE (StatusCode);
+  results.clear();
+
+  results.tagweight_bin_edges = m_binEdges;
+
+  if(rand_seed!=-1){
+    trfinf.rand.SetSeed(rand_seed);
+  }
+
+  unsigned int n_systs = m_eff_syst.size(); 
+  if(m_useSys){
+    trfinf.trfwsys_ex.resize(m_eff_syst.size());
+    trfinf.trfwsys_in.resize(m_eff_syst.size());
+  }
+  else{
+    n_systs = 1; //compute only the nominal
+    trfinf.trfwsys_ex.resize(1);
+    trfinf.trfwsys_in.resize(1);
+  }
+  std::vector<double> trf_weight_ex,  trf_weight_in;
+
+  for(unsigned int i =0; i< n_systs; i++){
+    trf_weight_ex.clear();
+    trf_weight_in.clear();
+
+    ANA_CHECK(GetTruthTagWeights(trfinf, trf_weight_ex, trf_weight_in, i));
+
+  }
+
+  results.syst_names.clear();
+
+  for(unsigned int i=0; i<trfinf.trfwsys_ex.size(); i++){
+  //  for(unsigned int i=0; i<Nsysts; i++){
+
+    results.map_trf_weight_ex[m_sys_name.at(i)].resize(trfinf.trfwsys_ex.at(i).size());
+    results.map_trf_weight_in[m_sys_name.at(i)].resize(trfinf.trfwsys_in.at(i).size());
+
+    //direct tagged SF
+    if(m_doDirectTag)
+      results.map_SF[m_sys_name.at(i)]=getEvtSF(trfinf,i);
+    
+    results.syst_names.push_back(m_sys_name.at(i));
+    
+    for(unsigned int j=0; j< trfinf.trfwsys_ex.at(i).size(); j++){
+      results.map_trf_weight_ex[m_sys_name.at(i)].at(j) = trfinf.trfwsys_ex.at(i).at(j);
+      results.map_trf_weight_in[m_sys_name.at(i)].at(j) = trfinf.trfwsys_in.at(i).at(j);
+
+    }
+  }
+
+  if(m_usePerm){
+  ANA_CHECK(getTagPermutation(trfinf,results.trf_chosen_perm_ex,results.trf_chosen_perm_in));
+  }
+  if(m_useQuntile){
+  ANA_CHECK(getQuantiles(trfinf,results.trf_bin_ex, results.trf_bin_in));
+  ANA_CHECK(generateRandomTaggerScores(results.trf_bin_ex, results.trf_bin_score_ex));
+  ANA_CHECK(generateRandomTaggerScores(results.trf_bin_in, results.trf_bin_score_in));
+  }
+  if(m_doDirectTag)
+    ANA_CHECK(getDirectTaggedJets(trfinf,results.is_tagged));
+  
+  return StatusCode::SUCCESS;
+
+}
+
+StatusCode BTaggingTruthTaggingTool::CalculateResults(std::vector<double>& pt, std::vector<double>& eta, std::vector<int>& flav, std::vector<double>& tagw, Analysis::TruthTagResults& results,int rand_seed){
+
+  ANA_CHECK_SET_TYPE (StatusCode);
+
+  TRFinfo trfinf;
+
+  ANA_CHECK(setJets(trfinf,pt, eta, flav, tagw));
+
+  return CalculateResults(trfinf,results,rand_seed);
+}
+
+StatusCode BTaggingTruthTaggingTool::CalculateResults(const xAOD::JetContainer& jets, Analysis::TruthTagResults& results,int rand_seed){
+
+  ANA_CHECK_SET_TYPE (StatusCode);
+
+  TRFinfo trfinf;
+
+  ANA_CHECK(setJets(trfinf,jets));
+
+  return CalculateResults(trfinf,results,rand_seed);
+}
+
+
+StatusCode BTaggingTruthTaggingTool::getAllEffMC(TRFinfo &trfinf){
+
+  float eff =1.;
+  float eff_all =1.;
+  trfinf.effMC.clear();
+  if(m_useQuntile == true || m_continuous == true){
+    for(auto op_appo: m_availableOP)
+      trfinf.effMC_allOP[op_appo].clear();
+  }
+  for(size_t i=0; i < trfinf.jets.size(); i++){
+    if(m_continuous){
+      eff=1.;
+      // loop on OP
+      int OP_index = 0;
+      for(const auto & op_appo: m_availableOP){
+	eff_all=1.;
+	//set a dumb value of the truth tag weight to get the different efficiency maps for each bin. to be improved..
+	if(OP_index+1 < (int) m_availableOP.size()){
+	  trfinf.jets.at(i).vars.jetTagWeight = (m_binEdges.at(OP_index)+m_binEdges.at(OP_index+1))/2.; //to-do: make it fancy? random distribution inside the bin probably?
+	}
+	else{
+	  trfinf.jets.at(i).vars.jetTagWeight = (m_binEdges.at(OP_index)+1)/2.; //only for 60% WP
+	}
+
+	CorrectionCode code = m_effTool->getMCEfficiency(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, eff_all) ;
+
+	if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	  ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
+	  return StatusCode::FAILURE;
+	}
+	trfinf.effMC_allOP[op_appo].push_back(eff_all);
+	OP_index++;
+
+      } // end loop on OP
+    } //inside Continuous
+    else{
+      eff=1.;
+      CorrectionCode code = m_effTool->getMCEfficiency(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, eff);
+      if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
+	return StatusCode::FAILURE;}
+      
+      trfinf.effMC.push_back(eff);
+      
+      if(m_useQuntile){
+	// loop on OP
+	for(const auto & op_appo: m_availableOP){
+	  
+	  if ( op_appo==m_OP) {
+	    trfinf.effMC_allOP[op_appo].push_back(eff);
+	    continue;
+	  }
+	  
+	  eff_all=1.;
+	  CorrectionCode code = m_effTool_allOP[op_appo]->getMCEfficiency(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, eff_all) ;
+	  
+	  if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	    ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
+	    return StatusCode::FAILURE;
+	  }
+	  
+	  trfinf.effMC_allOP[op_appo].push_back(eff_all);
+	} // end loop on OP
+      } // if useQuantile
+    } //!useContinuous
+  } // end loop on jets
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::getAllEffSF(TRFinfo &trfinf,int sys){
+  ANA_CHECK_SET_TYPE ( StatusCode );
+
+  trfinf.eff.clear();
+  if(!m_continuous){
+    trfinf.eff.resize(trfinf.effMC.size());
+    if(m_useQuntile){
+      for(const auto & op_appo: m_availableOP){
+	trfinf.eff_allOP[op_appo].clear();
+	trfinf.eff_allOP[op_appo].resize(trfinf.effMC.size());
+      }
+    }
+  }
+  else{
+    trfinf.eff.resize(trfinf.effMC_allOP[m_cutBenchmark].size());
+    for(const auto & op_appo: m_availableOP){
+      trfinf.eff_allOP[op_appo].clear();
+      trfinf.eff_allOP[op_appo].resize(trfinf.effMC_allOP[op_appo].size());
+    }
+  }
+  
+  if(m_ignoreSF && sys==0){
+    if(m_continuous){
+      for(int iop = (int) m_availableOP.size()-1; iop >= 0; iop--) { // loop on the tighter OPs
+	string op_appo = m_availableOP.at(iop);
+	if(!m_useQuntile &&  iop < (int) m_OperatingPoint_index) continue;
+	for(size_t ieff =0; ieff< trfinf.eff_allOP[op_appo].size(); ieff++){ //jets
+	  trfinf.eff_allOP[op_appo].at(ieff)= 0;   
+	  for(unsigned int p = iop; p<m_availableOP.size(); p++){ //add all the eff above the WP	   
+	    trfinf.eff_allOP[op_appo].at(ieff)+=trfinf.effMC_allOP[m_availableOP.at(p)].at(ieff);
+	  }
+	  if( op_appo == m_cutBenchmark)
+	    trfinf.eff.at(ieff) = trfinf.eff_allOP[m_cutBenchmark].at(ieff);
+	} //jets
+      } //OP
+    } //continuous
+    else{
+      for(size_t i =0; i< trfinf.effMC.size(); i++){
+	trfinf.eff.at(i)=trfinf.effMC.at(i);
+	if(m_useQuntile){
+	  for(const auto & op_appo: m_availableOP){
+	    trfinf.eff_allOP[op_appo].at(i)=trfinf.effMC_allOP[op_appo].at(i);
+	  }
+	}
+      }
+    }
+    return StatusCode::SUCCESS;
+  }
+
+  if(m_ignoreSF && sys==0){
+    ATH_MSG_ERROR("Tryig to access SF systematics but ignoring SF");
+    return StatusCode::FAILURE;
+  }
+
+  float SF =1.;
+  float SF_all =1.;
+
+    if(sys!=0 && m_useSys){
+      ATH_MSG_DEBUG("applying the syst: " <<m_sys_name[sys]);
+      ANA_CHECK_THROW( m_effTool->applySystematicVariation(m_eff_syst[sys]) );
+    if(m_useQuntile && !m_continuous){
+      for(const auto & op_appo: m_availableOP){
+  if (op_appo==m_OP) continue;
+  ANA_CHECK( m_effTool_allOP[op_appo]->applySystematicVariation(m_eff_syst[sys]) );
+      }
+    }
+  }
+
+  if(m_continuous){
+    for(int iop = (int) m_availableOP.size()-1; iop >= 0; iop--) {
+      std::string op_appo = m_availableOP.at(iop);
+      if(!m_useQuntile &&  iop < (int) m_OperatingPoint_index) continue;
+      for(size_t i=0; i<trfinf.jets.size(); i++){
+	SF=1.;
+	//set a dumb value of the truth tag weight to get the different efficiency maps for each bin. to be improved..
+        if(iop+1 < (int) m_availableOP.size()){
+	trfinf.jets.at(i).vars.jetTagWeight = (m_binEdges.at(iop)+m_binEdges.at(iop+1))/2.; //to-do: make it fancy? random distribution for the tagger score
+	}
+	else{
+	  trfinf.jets.at(i).vars.jetTagWeight = (m_binEdges.at(iop)+1.)/2.;
+	}	  
+	
+	CorrectionCode code = m_effTool->getScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, SF) ;
+	if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	  ATH_MSG_ERROR("BTaggingEfficiencyTool::getScaleFactor returned CorrectionCode::Error");
+	  return StatusCode::FAILURE;
+	}
+
+	trfinf.eff_allOP[op_appo].at(i)=trfinf.effMC_allOP[op_appo].at(i)*SF;
+
+      //now sum all the corrected MC Eff together
+	if(iop+1 < (int) m_availableOP.size()){
+	    trfinf.eff_allOP[op_appo].at(i)+=trfinf.eff_allOP[m_availableOP.at(iop+1)].at(i); //they are already corrected for SF
+	}
+	if( op_appo == m_cutBenchmark)
+	  trfinf.eff.at(i) = trfinf.eff_allOP[m_cutBenchmark].at(i);
+      } //jets
+    } //OP
+  } //continuous
+  
+  else{
+    for(unsigned int i=0; i<trfinf.jets.size(); i++){
+      SF=1.;
+      CorrectionCode code = m_effTool->getScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, SF) ;
+      if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	ATH_MSG_ERROR("BTaggingEfficiencyTool::getScaleFactor returned CorrectionCode::Error");
+	return StatusCode::FAILURE;
+      }
+      trfinf.eff.at(i) = trfinf.effMC.at(i)*SF;
+      if(m_useQuntile){
+	// loop on OP
+	for(const auto & op_appo: m_availableOP){
+	  if (op_appo==m_OP) {
+	    trfinf.eff_allOP[op_appo].at(i)=trfinf.effMC.at(i)*SF;
+	    continue;
+	  }
+	  SF_all=1.;
+	  CorrectionCode code = m_effTool_allOP[op_appo]->getScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, SF_all) ;
+	  if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+	    ATH_MSG_ERROR("BTaggingEfficiencyTool::getScaleFactor returned CorrectionCode::Error");
+	    return StatusCode::FAILURE;
+	  }
+	  
+	  trfinf.eff_allOP[op_appo].at(i) = trfinf.effMC_allOP[op_appo].at(i)*SF_all;
+	} // end loop on OP
+      } // if useQuantile
+    } //!Continuous
+  } //jets
+  
+  CP::SystematicSet defaultSet;
+  ANA_CHECK( m_effTool->applySystematicVariation(defaultSet) );
+  if(m_useQuntile && !m_continuous){
+    for(const auto & op_appo: m_availableOP){
+      ANA_CHECK( m_effTool_allOP[op_appo]->applySystematicVariation(defaultSet) );
+    }
+  }
+  
+  return StatusCode::SUCCESS;
+}
+
+std::vector<std::vector<bool> > BTaggingTruthTaggingTool::generatePermutations(int njets, int tags, int start){
+  std::vector<std::vector<bool> > perm;
+  std::vector<std::vector<bool> > temp_perm;
+  if(tags==0){
+    std::vector<bool> tags(njets,false);
+    perm.push_back(tags);
+  }
+  else if(tags == njets) {
+    std::vector<bool> tags(njets,true);
+    perm.push_back(tags);
+  }
+  else {
+    for(int i=start; i<njets;i++){
+      temp_perm = generatePermutations(njets,tags-1,i+1);
+      for(unsigned int j=0; j<temp_perm.size(); j++){
+        temp_perm.at(j).at(i)=true;
+        perm.push_back(temp_perm.at(j));
+      }
+    }
+  }
+  return perm;
+}
+
+
+double BTaggingTruthTaggingTool::trfWeight(TRFinfo &trfinf,const std::vector<bool> &tags){
+  double weight = 1;
+  for (unsigned int j=0; j<tags.size();j++) {
+    double trf = 0.;
+    trf = trfinf.eff[j];
+    if(trf>1.) {
+      ATH_MSG_WARNING("Truth Tagging weight > 1. --> setting it to 1. check maps!");
+      trf = 1.;
+    }
+    if(tags.at(j)) weight *= trf;
+    else weight *= (1.-trf);
+  } // end loop over jets
+  return weight;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::getTRFweight(TRFinfo &trfinf,unsigned int nbtag, bool isInclusive, int sys){
+
+  unsigned int njets = trfinf.njets;
+  // Consider permutations of njet jets with up to limit b-tags
+  unsigned int limit = (njets > 7) ? 8 : njets+1;
+
+  // Permutations: njets, ntags, permutations
+  // From .h: std::map<int, std::vector<std::vector<std::vector<bool> > > > trfinf.perms;
+
+  if (trfinf.perms.find(njets)==trfinf.perms.end()){   // if I don't have already saved the possible permutations for njet
+    trfinf.perms[njets] = std::vector<std::vector<std::vector<bool> > >(limit);
+    for(unsigned int i=0;i<limit;i++)
+      trfinf.perms[njets].at(i) = generatePermutations(njets,i);
+  }
+
+  trfinf.permsWeight.clear(), trfinf.permsWeight.resize(limit); // trfinf.permsWeight.at(i).at(j): TRF weight of the j-th perm with i b-tags
+  trfinf.permsSumWeight.clear(), trfinf.permsSumWeight.resize(limit); // trfinf.permsSumWeight.at(i).at(j): partial sum of  TRF weight of the permutations with i b-tags up to j (0,1,..,j-th) perm. Used in the choice of the selected permutation
+
+  // compute TRF weight
+  unsigned int max = nbtag+1; // from 0 to nbtag b-tags --> nbtag+1 positions
+  trfinf.trfwsys_ex[sys].clear(), trfinf.trfwsys_in[sys].clear();
+  trfinf.trfwsys_ex[sys].resize(max), trfinf.trfwsys_in[sys].resize(max);
+
+  if(sys == 0) { // nominal case --> clear and resize elements of trfinf
+    trfinf.perm_ex.clear(), trfinf.perm_in.clear(); // vector<vector<bool>> --> for each number of tags the chosen permutation
+    trfinf.perm_ex.resize(max),  trfinf.perm_in.resize(max);
+    trfinf.permprob_ex.clear(), trfinf.permprob_in.clear(); // probability of the perm in trfinf.perm_ex/in
+    trfinf.permprob_ex.resize(max),  trfinf.permprob_in.resize(max);
+  }
+  if(isInclusive) {
+    for(unsigned int i=0; i<limit; i++) { // note: I consider maximum limit tags. It's an approximation
+      std::vector<double> weights;
+      double sum = 0., w = 0.;
+      trfinf.permsWeight.at(i).clear();
+      trfinf.permsSumWeight.at(i).clear();
+      trfinf.permsWeight.at(i).resize(trfinf.perms[njets].at(i).size());
+      trfinf.permsSumWeight.at(i).resize(trfinf.perms[njets].at(i).size());
+
+      // loop on all the permutations with i tags
+      for(unsigned int p=0; p<trfinf.perms[njets].at(i).size(); p++) {
+	w = trfWeight(trfinf,trfinf.perms[njets].at(i).at(p));
+	sum+=w;
+	//trfinf.permsWeight.at(i).push_back(w); //old way to do it without resizing, keep it for the moment
+	//trfinf.permsSumWeight.at(i).push_back(sum);
+	trfinf.permsWeight.at(i).at(p) = w;
+        trfinf.permsSumWeight.at(i).at(p) = sum;
+
+	ATH_MSG_DEBUG("nbtag = " << i << "  wei = " << w << "  sum = " << sum);
+      }
+      if(i<limit && i<max) {
+  // note: I need to already have the exclusive weights filled to compite the inclusive
+	trfinf.trfwsys_ex[sys].at(i) = sum; // sum of TRF weights for all perm with i b-tags
+	if(i == 0) trfinf.trfwsys_in[sys].at(0) = 1.;
+	else trfinf.trfwsys_in[sys].at(i) = trfinf.trfwsys_in[sys].at(i-1) - trfinf.trfwsys_ex[sys].at(i-1); // P(>=4) = P(>=3) - P(==3)
+	ATH_MSG_DEBUG("i = " << i << "  sum = " << sum << "  TRF in " << trfinf.trfwsys_in[0].at(i) << "  ex = " << trfinf.trfwsys_ex[0].at(i));
+      }
+    }
+    ATH_MSG_DEBUG("before return, nbtag = " << nbtag << "  size de trfinf.trfwsys_in[sys] = " << trfinf.trfwsys_in[sys].size());
+    return StatusCode::SUCCESS;
+  }
+  else { // exclusive case, only one calculation needed
+    std::vector<double> weights;
+    double sum = 0., w = 0.;
+    size_t size = trfinf.perms[njets].at(nbtag).size(); 
+    trfinf.permsWeight.at(nbtag).clear();
+    trfinf.permsSumWeight.at(nbtag).clear();    
+    trfinf.permsWeight.at(nbtag).resize(size);
+    trfinf.permsSumWeight.at(nbtag).resize(size);
+    // loop on all the permutations with i tags
+    for(unsigned int p=0; p<trfinf.perms[njets].at(nbtag).size(); p++) {
+      
+      w = trfWeight(trfinf,trfinf.perms[njets].at(nbtag).at(p));
+      sum+=w;
+      //      trfinf.permsWeight.at(nbtag).push_back(w); //old way, before resizing: keep it for the moment
+      //      trfinf.permsSumWeight.at(nbtag).push_back(sum);
+      trfinf.permsWeight.at(nbtag).at(p) = w;
+      trfinf.permsSumWeight.at(nbtag).at(p) = sum;
+    }
+    trfinf.trfwsys_ex[sys].at(nbtag) = sum;
+    return StatusCode::SUCCESS;
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::getTagPermutation(TRFinfo &trfinf, std::vector<std::vector<bool> > &trf_chosen_perm_ex, std::vector<std::vector<bool> > &trf_chosen_perm_in){
+  trf_chosen_perm_ex.resize(m_nbtag+1);
+  trf_chosen_perm_in.resize(m_nbtag+1);
+  trf_chosen_perm_ex = trfinf.perm_ex;
+  trf_chosen_perm_in = trfinf.perm_in;
+  std::string print_perm = "Permutation: ";
+  for(auto perm: trfinf.perm_ex){
+    for(auto is: perm) {
+      if(is) print_perm+=std::to_string(1);
+      else print_perm+=std::to_string(0);
+      print_perm+="  ";
+    }
+  }
+  ATH_MSG_DEBUG(print_perm);
+  return StatusCode::SUCCESS;
+}
+
+StatusCode BTaggingTruthTaggingTool::chooseAllTagPermutation(TRFinfo &trfinf,unsigned int nbtag){
+
+  ANA_CHECK_SET_TYPE (StatusCode);
+
+  if(!m_usePerm){
+    return StatusCode::FAILURE;
+  }
+
+  unsigned int njets = trfinf.njets;
+  unsigned int limit = (njets > 7) ? 8 : njets+1;
+  unsigned int max = (njets < nbtag+1) ? limit : nbtag+1;
+
+  trfinf.perm_ex.clear(), trfinf.perm_ex.resize(nbtag+1);
+  trfinf.perm_in.clear(), trfinf.perm_in.resize(nbtag+1);
+
+  trfinf.permprob_ex.clear(), trfinf.permprob_ex.resize(nbtag+1);
+  trfinf.permprob_in.clear(), trfinf.permprob_in.resize(nbtag+1);
+
+  for(unsigned int i=0; i<max; i++) { // need +1 as 0 is included
+    ANA_CHECK(chooseTagPermutation(trfinf,i,false));
+    ANA_CHECK(chooseTagPermutation(trfinf,i,true));
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode BTaggingTruthTaggingTool::chooseTagPermutation(TRFinfo &trfinf,unsigned int nbtag, bool isIncl){
+  std::vector<double> incl;
+  std::vector<std::pair<unsigned int, unsigned int> > trackPerm;
+  double sum = 0;
+  if(isIncl) {
+    for(unsigned int itag=nbtag; itag < trfinf.permsWeight.size(); itag++) {
+      for(unsigned int ip = 0; ip < trfinf.permsWeight.at(itag).size(); ip++) {
+    sum += trfinf.permsWeight.at(itag).at(ip);
+    incl.push_back(sum);
+    trackPerm.push_back(std::make_pair(itag,ip));
+      }
+    }
+  }
+  else { // in exclusive case
+    sum = trfinf.permsSumWeight.at(nbtag).back();
+    incl = trfinf.permsSumWeight.at(nbtag);
+    for(unsigned int ip = 0; ip < trfinf.permsSumWeight.at(nbtag).size(); ip++) trackPerm.push_back(std::make_pair(nbtag,ip));
+  }
+  double theX = trfinf.rand.Uniform(sum);
+  for(unsigned int ip=0; ip < incl.size(); ip++) {
+    ATH_MSG_DEBUG("incl.at(ip): " << incl.at(ip) << "  theX: " << theX);
+    if(incl.at(ip) >= theX) {
+      if(isIncl) {
+  trfinf.perm_in.at(nbtag) = trfinf.perms[trfinf.njets].at(trackPerm.at(ip).first).at(trackPerm.at(ip).second);
+  trfinf.permprob_in.at(nbtag) = trfinf.permsWeight.at(trackPerm.at(ip).first).at(trackPerm.at(ip).second) / trfinf.trfwsys_in[0].at(nbtag);
+      }
+      else {
+	trfinf.perm_ex.at(nbtag) = trfinf.perms[trfinf.njets].at(trackPerm.at(ip).first).at(trackPerm.at(ip).second);
+	trfinf.permprob_ex.at(nbtag) = trfinf.permsWeight.at(trackPerm.at(ip).first).at(trackPerm.at(ip).second) / trfinf.trfwsys_ex[0].at(nbtag);
+      }
+      return StatusCode::SUCCESS;
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+
+///// tag bins  //////////////////////
+// Cheatsheet:
+// returns 5 if between 60% and 0%
+// returns 4 if between 70% and 60%
+// returns 3 if between 77% and 70%
+// returns 2 if between 85% and 77%
+// returns 1 if between 100% and 85%
+// return -1 if not in b-tagging acceptance
+//////////////////////
+
+
+StatusCode BTaggingTruthTaggingTool::getQuantiles(TRFinfo &trfinf,std::vector<std::vector<int> > &trf_bin_ex, std::vector<std::vector<int> > &trf_bin_in){
+  trf_bin_ex.resize(trfinf.tbins_ex.size());
+  for(unsigned int i =0; i<trfinf.tbins_ex.size(); i++)
+    trf_bin_ex.at(i).resize(trfinf.tbins_ex.at(i).size());
+
+  trf_bin_in.resize(trfinf.tbins_in.size());
+  for(unsigned int i =0; i<trfinf.tbins_in.size(); i++)
+    trf_bin_in.at(i).resize(trfinf.tbins_in.at(i).size());
+  // increasing the value by 1 to match conventions in selectionTool
+  for(unsigned int i =0; i<trfinf.tbins_ex.size(); i++)
+    for(unsigned int j=0; j<trfinf.tbins_ex.at(i).size(); j++)
+      trf_bin_ex.at(i).at(j)=trfinf.tbins_ex.at(i).at(j) +1;
+
+  for(unsigned int i =0; i<trfinf.tbins_in.size(); i++)
+    for(unsigned int j=0; j<trfinf.tbins_in.at(i).size(); j++)
+      trf_bin_in.at(i).at(j)=trfinf.tbins_in.at(i).at(j) +1;
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode BTaggingTruthTaggingTool::chooseAllTagBins(TRFinfo &trfinf){
+  ANA_CHECK_SET_TYPE (StatusCode);
+  trfinf.tbins_ex.clear();
+  trfinf.tbins_in.clear();
+  trfinf.tbins_ex.resize( trfinf.trfwsys_ex[0].size());
+  trfinf.tbins_in.resize( trfinf.trfwsys_in[0].size());
+
+  trfinf.binsprob_ex.clear();
+  trfinf.binsprob_in.clear();
+  trfinf.binsprob_ex.resize( trfinf.trfwsys_ex[0].size());
+  trfinf.binsprob_in.resize( trfinf.trfwsys_in[0].size());
+
+  if(trfinf.perm_ex.size() != trfinf.perm_in.size()) ATH_MSG_WARNING("Different sizes in exclusive and inclusive permutation choices");
+
+  for(unsigned int nb=0; nb<trfinf.perm_ex.size(); nb++) {
+    ANA_CHECK(chooseTagBins_cum(trfinf,trfinf.perm_ex.at(nb), false, nb));
+    ANA_CHECK(chooseTagBins_cum(trfinf,trfinf.perm_in.at(nb), true, nb));
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+// chiara: non posso uniformare il codice con getTagBinsConfProb??
+StatusCode BTaggingTruthTaggingTool::chooseTagBins_cum(TRFinfo &trfinf,std::vector<bool> &tagconf, bool isIncl, unsigned int nbtag){
+  std::vector<int> btagops;
+
+  std::vector<double> incl;
+  double prob = 1.;
+
+  for(unsigned int j=0; j<tagconf.size(); j++) {
+    if(tagconf.at(j)) { // tagged jet
+      double sum=0.;
+      incl.clear();
+      for(int iop = (int)trfinf.eff_allOP.size()-1; iop >= (int)m_OperatingPoint_index; iop--) { // loop on the tighter OPs
+	sum = trfinf.eff_allOP[m_availableOP.at(iop)][j];
+	incl.push_back(sum);
+      }
+      double theX = trfinf.rand.Uniform(sum);
+
+      for(unsigned int k=0; k<incl.size(); k++) {
+  double valm1 = 0.;
+  if(k!=0) valm1 = incl.at(k-1);
+    if(incl.at(k) >= theX) {
+      btagops.push_back(m_availableOP.size()-k);
+    prob *= (incl.at(k)-valm1) / sum;
+      break;
+    }
+      }
+    }
+    else { // untagged jet
+      double sum=0.;
+      incl.clear();
+      incl.push_back(sum); // fill the "0_0" OP as no real value affected and start the loop at 1
+      for(unsigned int iop=0; iop<=m_OperatingPoint_index; iop++) { // need to include the chosen tag cut to have the last MV1 bin of untagged jets filled, start at 0 with cumulative as iop = 0 = first OP
+    // sum = 1 - trf here
+    sum = 1 - trfinf.eff_allOP[m_availableOP.at(iop)][j];
+    incl.push_back(sum);
+      }
+
+      double theX = trfinf.rand.Uniform(sum);
+      for(unsigned int k=1; k<incl.size(); k++) {
+        if(incl.at(k) >= theX){
+    btagops.push_back(k-1);
+    prob *= (incl.at(k) - incl.at(k-1)) / sum;
+          break;
+        }
+      }
+    }
+  }
+  if(btagops.size() != tagconf.size()) {
+    ATH_MSG_ERROR("You should not be here -> wrong size of tag bins vector");
+    return StatusCode::FAILURE;
+  }
+  if(isIncl) {
+    trfinf.tbins_in.at(nbtag) = btagops;
+    trfinf.binsprob_in.at(nbtag) = prob;
+    ATH_MSG_DEBUG("incl, nbtag " << nbtag << "   prob " << prob);
+  }
+  else {
+    trfinf.tbins_ex.at(nbtag) = btagops;
+    trfinf.binsprob_ex.at(nbtag) = prob;
+    ATH_MSG_DEBUG("excl, nbtag " << nbtag << "   prob " << prob);
+  }
+  return StatusCode::SUCCESS;
+}
+
+
+
+double BTaggingTruthTaggingTool::getTagBinsRW(TRFinfo &trfinf,bool isIncl, unsigned int nbtag){
+
+  if((!isIncl && trfinf.binsprob_ex.size() == 0) || (isIncl && trfinf.binsprob_in.size() == 0)) {
+    ATH_MSG_ERROR("Need to choose quantiles before computing the reweighting");
+    exit(-1);
+  }
+
+  double tbw = 0.;
+  double prob_sys=1.;
+
+  if(isIncl) {
+    prob_sys=getTagBinsConfProb(trfinf,trfinf.tbins_in.at(nbtag));
+    tbw = prob_sys/trfinf.binsprob_in.at(nbtag);
+    return tbw;
+  }
+  else {
+    prob_sys=getTagBinsConfProb(trfinf,trfinf.tbins_ex.at(nbtag));
+    tbw = prob_sys/trfinf.binsprob_ex.at(nbtag);
+    return tbw;
+  }
+}
+
+
+double BTaggingTruthTaggingTool::getTagBinsConfProb(TRFinfo &trfinf,std::vector<int> &tagws){
+  double prob = 1.;
+  for(unsigned int j=0; j<tagws.size(); j++) {
+    if((unsigned int)tagws.at(j) > m_OperatingPoint_index) { // tagged
+      double prevBinW = 0.;
+      int mOP = m_availableOP.size();
+      if(tagws.at(j) != mOP) { // not the last tag-bin
+  prevBinW =  trfinf.eff_allOP[m_availableOP.at(tagws.at(j))][j];
+      }
+      // prob *= (eff*SF-exactly-that-bin)/(ef*SF-all-tagged-bins)
+      // (eff*SF-exactly-that-bin): eff(==60) = eff(70) - eff(60) --> eff(==5) = eff(4)-eff(5)
+	prob *= (trfinf.eff_allOP[m_availableOP.at(tagws.at(j)-1)][j] - prevBinW) /  (trfinf.eff_allOP[m_availableOP.at(m_OperatingPoint_index)][j]);
+      ATH_MSG_DEBUG("prob " << prob);
+    }
+    else { // untagged
+      double prevBinW = 0.;
+      if(tagws.at(j) != 0) {
+  prevBinW = 1 - trfinf.eff_allOP[m_availableOP.at(tagws.at(j)-1)][j];
+      }
+      prob *= ((1 - trfinf.eff_allOP[m_availableOP.at(tagws.at(j))][j]) - prevBinW) / (1 - trfinf.eff_allOP[m_availableOP.at(m_OperatingPoint_index)][j]);
+      ATH_MSG_DEBUG("prob " << prob);
+    }
+  }
+  return prob;
+}
+
+StatusCode BTaggingTruthTaggingTool::getDirectTaggedJets(TRFinfo &trfinf,std::vector<bool> &is_tagged){
+  
+  is_tagged.clear();
+  std::vector<int> appo;
+  
+  for(const auto jet : trfinf.jets) {
+    ATH_MSG_DEBUG("pt " << jet.vars.jetPt << "   eta " << jet.vars.jetEta << "   wei " << jet.vars.jetTagWeight);
+    bool is_btagged = false;
+    if(!m_continuous)
+      is_btagged = static_cast<bool>(m_selTool->accept(jet.vars.jetPt, jet.vars.jetEta, jet.vars.jetTagWeight));
+    else{
+      int quantile = m_selTool->getQuantile(jet.vars.jetPt, jet.vars.jetEta, jet.vars.jetTagWeight);
+      is_btagged = quantile > (int) m_OperatingPoint_index ? true : false;
+      ATH_MSG_DEBUG("quantile " <<quantile <<" m_OperatingPoint_index " <<m_OperatingPoint_index <<" is_tagged? " <<is_btagged);
+
+    }
+
+    ATH_MSG_DEBUG("is tagged? " << is_btagged);
+    if(is_btagged) is_tagged.push_back(1);
+    else is_tagged.push_back(0);
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+
+double BTaggingTruthTaggingTool::getEvtSF(TRFinfo &trfinf,int sys){
+  ANA_CHECK_SET_TYPE (StatusCode);
+  double SF = 1.;
+  std::vector<bool> is_tagged;
+  ANA_CHECK_THROW( getDirectTaggedJets(trfinf,is_tagged) );
+
+  if(sys!=0 && m_useSys) {
+
+    ANA_CHECK_THROW( m_effTool->applySystematicVariation(m_eff_syst[sys]) );
+  }
+
+  for(unsigned int i =0; i< trfinf.jets.size(); i++) {
+    bool is_btagged = is_tagged.at(i);
+    float ineffSF =1;
+    float effSF=1;
+
+    if(is_btagged){    // tagged --> look at sf
+      // CorrectionCode code = m_effTool->getScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, ineffSF);
+      // if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+      //   ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
+      //   return -1.0;
+      // }
+      ANA_CHECK_THROW(m_effTool->getScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, ineffSF));
+
+      SF*=ineffSF;
+    }
+    else{    // not tagged --> loop at ineff SF
+      // CorrectionCode code = m_effTool->getInefficiencyScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, effSF);
+      // if(!(code==CorrectionCode::Ok || code==CorrectionCode::OutOfValidityRange)){
+      //   ATH_MSG_ERROR("BTaggingEfficiencyTool::getMCEfficiency returned CorrectionCode::Error");
+      //   return -1.0;
+      // }
+
+      ANA_CHECK_THROW(m_effTool->getInefficiencyScaleFactor(trfinf.jets.at(i).flav, trfinf.jets.at(i).vars, effSF));
+      SF *= effSF;
+    }
+  }
+
+  if(sys!=0 && m_useSys) {  // reset syst to nominal
+    CP::SystematicSet defaultSet;
+
+    ANA_CHECK_THROW( m_effTool->applySystematicVariation(defaultSet) );
+  }
+  return SF;
+}
+
+
+StatusCode BTaggingTruthTaggingTool::check_syst_range(unsigned int sys){
+  if(sys < m_eff_syst.size()) return StatusCode::SUCCESS;
+  ATH_MSG_ERROR(sys << " Out of range of available systematics");
+  return StatusCode::FAILURE;
+}
+
+
+
+BTaggingTruthTaggingTool::~BTaggingTruthTaggingTool(){
+
+  // delete trfinf.jets;
+
+}
+
+
+int BTaggingTruthTaggingTool::jetFlavourLabel (const xAOD::Jet& jet){
+  if (m_coneFlavourLabel)
+    return (m_oldConeFlavourLabel) ? ConeFinalPartonFlavourLabel(jet) : ExclusiveConeHadronFlavourLabel(jet);
+  else
+    return GAFinalHadronFlavourLabel(jet);
+}
+
+int BTaggingTruthTaggingTool::GAFinalHadronFlavourLabel (const xAOD::Jet& jet) {
+
+  const std::string labelB = "GhostBHadronsFinal";
+  const std::string labelC = "GhostCHadronsFinal";
+  const std::string labelTau = "GhostTausFinal";
+
+  std::vector<const IParticle*> ghostB;
+  if (jet.getAssociatedObjects<IParticle>(labelB, ghostB) && ghostB.size() > 0) return 5;
+  std::vector<const IParticle*> ghostC;
+  if (jet.getAssociatedObjects<IParticle>(labelC, ghostC) && ghostC.size() > 0) return 4;
+  std::vector<const IParticle*> ghostTau;
+  if (jet.getAssociatedObjects<IParticle>(labelTau, ghostTau) && ghostTau.size() > 0) return 15;
+
+
+  return 0;
+}
+
+int BTaggingTruthTaggingTool::ConeFinalPartonFlavourLabel (const xAOD::Jet& jet){
+  // default label means "invalid"
+  int label = -1;
+  // First try the new naming scheme
+  if (jet.getAttribute("ConeTruthLabelID",label)) return label;
+  // If that fails, revert to the old scheme. In this case, further testing is not very useful
+  jet.getAttribute("TruthLabelID", label);
+  return label;
+}
+
+int BTaggingTruthTaggingTool::ExclusiveConeHadronFlavourLabel (const xAOD::Jet& jet){
+  // default label means "invalid"
+  int label = -1;
+  // We don't check the return value, as we would not be able to handle it gracefully anyway
+  jet.getAttribute("HadronConeExclTruthLabelID",label);
+  return label;
+}
+
+// local utility function: trim leading and trailing whitespace in the property strings
+std::string trim(const std::string& str,
+		 const std::string& whitespace = " \t") {
+  const auto strBegin = str.find_first_not_of(whitespace);
+  if (strBegin == std::string::npos)
+    return ""; // no content
+
+  const auto strEnd = str.find_last_not_of(whitespace);
+  const auto strRange = strEnd - strBegin + 1;
+
+  return str.substr(strBegin, strRange);
+}
+
+
+std::vector<std::string> BTaggingTruthTaggingTool::split(const std::string& str, char token) {
+  std::vector<std::string> result;
+  if (str.size() > 0) {
+    std::string::size_type end;
+    std::string tmp(str);
+    do {
+      end = tmp.find(token);
+      std::string entry = trim(tmp.substr(0,end));
+      if (entry.size() > 0) result.push_back(entry);
+      if (end != std::string::npos) tmp = tmp.substr(end+1);
+    } while (end != std::string::npos);
+  }
+  return result;
+}
+
+StatusCode BTaggingTruthTaggingTool::generateRandomTaggerScores(std::vector< std::vector<int> > &quantiles, std::vector< std::vector<double> > &scores){
+
+  //quantiles:
+  // returns 5 if between 60% and 0%
+  // returns 4 if between 70% and 60%
+  // returns 3 if between 77% and 70%
+  // returns 2 if between 85% and 77%
+  // returns 1 if between 100% and 85%
+  //m_binEdges
+  // 3 60%
+  // 2 70%
+  // 1 77%
+  // 0 85%
+
+  scores.clear();
+
+  TRandom3 random;
+
+  scores.resize(quantiles.size());
+  for(unsigned int i=0; i <quantiles.size(); i++ ){
+
+    scores.at(i).resize(quantiles.at(i).size());
+
+    for(unsigned int j=0; j <quantiles.at(i).size(); j++ ){
+
+        int quantile = quantiles.at(i).at(j);
+
+        if(quantile == 1){
+          double lowTaggerScore = -1.0;
+          if(m_taggerName.find("MV2") != string::npos){ lowTaggerScore = -1.0; }
+          if(m_taggerName.find("DL1") != string::npos){ lowTaggerScore = -20.0;}
+
+          scores.at(i).at(j) = lowTaggerScore + random.Uniform()*( m_binEdges.at(0)-lowTaggerScore );
+        }else if(quantile == 5){
+          double highTaggerScore = +1.0;
+          if(m_taggerName.find("MV2") != string::npos){ highTaggerScore = 1.0; }
+          if(m_taggerName.find("DL1") != string::npos){ highTaggerScore = 20.0; }
+
+          scores.at(i).at(j) = m_binEdges.at(3) + random.Uniform()*( highTaggerScore-m_binEdges.at(3) );
+        }else{
+          scores.at(i).at(j) = m_binEdges.at(quantile-2) + random.Uniform()*( m_binEdges.at(quantile-1)-m_binEdges.at(quantile-2) );
+        }
+    }
+  }
+
+  return StatusCode::SUCCESS;
+
+}
+
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/LinkDef.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/LinkDef.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ea08cfd6eb495650249d8a8cd0d40f6f3aef7b8
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/Root/LinkDef.h
@@ -0,0 +1,18 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "xAODBTaggingEfficiency/TruthTagResults.h"
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ nestedclass;
+
+#pragma link C++ namespace Analysis;
+#pragma link C++ class Analysis::TruthTagResults;
+
+#endif
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/ToolTester.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/ToolTester.cxx
index 6e8d1936c7b3e68fec72f160764e3b1b054e21b6..daf681e37eab416c54420d3a6efa5c116c61495f 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/ToolTester.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/ToolTester.cxx
@@ -5,7 +5,7 @@
 // $Id$
 
 #include "xAODJet/JetContainer.h"
-#include "CalibrationDataInterface/CalibrationDataInterfaceROOT.h"
+//#include "CalibrationDataInterface/CalibrationDataInterfaceROOT.h"
 
 #include "ToolTester.h"
 
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/components/xAODBTaggingEfficiency_entries.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/components/xAODBTaggingEfficiency_entries.cxx
index 9322d19701c8eeb07d14dd2ac852b86b336b034d..3cedaaa3fb4808ed17ba0c68430314cbf56b6a23 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/components/xAODBTaggingEfficiency_entries.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/src/components/xAODBTaggingEfficiency_entries.cxx
@@ -1,11 +1,18 @@
+
+
 #include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
 #include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"
+#include "xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h"
+#include "xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h"
+
 
 #include "../ToolTester.h"
-// Should probably alter the namespace 
+// Should probably alter the namespace
 
 DECLARE_COMPONENT( BTaggingEfficiencyTool )
 DECLARE_COMPONENT( BTaggingSelectionTool )
+DECLARE_COMPONENT( BTaggingTruthTaggingTool )
+DECLARE_COMPONENT( BTaggingEigenVectorRecompositionTool )
 
 DECLARE_COMPONENT( BTagToolTester )
 
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEfficiencyToolTester.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEfficiencyToolTester.cxx
index 87106c843d505bb91c373f08d873c934462b6616..3aebe5cec7bde09e01bf4c156a542badd52fd4fb 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEfficiencyToolTester.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEfficiencyToolTester.cxx
@@ -3,11 +3,12 @@
 */
 
 
-#ifdef ROOTCORE
+//#ifdef XAOD_STANDALONE
 #   include "xAODRootAccess/TStore.h"
-#endif // ROOTCORE
+//#endif // XAOD_STANDALONE
 
-#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
+#include <AsgTools/AnaToolHandle.h>
+#include "FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h"
 
 #include <string>
 #include <iomanip>
@@ -16,49 +17,50 @@ using CP::CorrectionCode;
 using CP::SystematicCode;
 
 int main() {
-  
+  bool retval = true;
   xAOD::TStore store;
+  
 
-  BTaggingEfficiencyTool * tool = new BTaggingEfficiencyTool("BTagTest");
-  // tagger name as specified in the CDI file
-  StatusCode code = tool->setProperty("TaggerName",          "MV2c10");
-  if (code != StatusCode::SUCCESS) std::cout << "error setting BTaggingEfficiencyTool TaggerName property" << std::endl;
-  // operating point as specified in the CDI file
-  code = tool->setProperty("OperatingPoint",      "FixedCutBEff_77");
-  if (code != StatusCode::SUCCESS) std::cout << "error setting BTaggingEfficiencyTool OperatingPoint property" << std::endl;
-  // jet collection name as specified in the CDI file (for 2012, this contains also the JVF specification)
-  code = tool->setProperty("JetAuthor",           "AntiKt4EMTopoJets");
-  if (code != StatusCode::SUCCESS) std::cout << "error setting BTaggingEfficiencyTool JetAuthor property" << std::endl;
-  // name of the CDI file
-  code = tool->setProperty("ScaleFactorFileName", "13TeV/2016-20_7-13TeV-MC15-CDI-2017-04-24_v1.root");
-  if (code != StatusCode::SUCCESS) std::cout << "error setting BTaggingEfficiencyTool ScaleFactorFileName property" << std::endl;
-  // calibration specification (there should always be a "default" available so this doesn't need to be set
-  // tool->setProperty("ScaleFactorBCalibration", "ttbar_PDF_7b_SF");
+  std::string taggerName = "DL1";
+  std::string workingPointName = "FixedCutBEff_70";
+
+  asg::AnaToolHandle<IBTaggingEfficiencyTool> tool("BTaggingEfficiencyTool/BTagEffTest");
+  StatusCode code1 = tool.setProperty("ScaleFactorFileName","xAODBTaggingEfficiency/13TeV/2019-21-13TeV-MC16-CDI-2019-10-07_v1.root" );
+  StatusCode code2 = tool.setProperty("TaggerName",    taggerName  );
+  StatusCode code3 = tool.setProperty("OperatingPoint", workingPointName);
+  StatusCode code4 = tool.setProperty("JetAuthor",      "AntiKt4EMPFlowJets_BTagging201810" );
+  
+  //provide a file which tells the tool which efficiency maps to use, and connects sample DSIDs to the right efficiency map.
+  //you can find a tool to automatically create this config file here: https://gitlab.cern.ch/mstamenk/automate-hadronisation-information
+  StatusCode code5 = tool.setProperty("EfficiencyConfig","/afs/cern.ch/work/j/jshlomi/public/example_eff_config.txt");
+  
   // specify an aggressive ("Tight") or not-so-aggressive ("Medium") eigenvector suppression scheme
-  //         (this needs information stored in the calibration objects which will not be available for older files)
-  // optionally, specify non-default and multiple efficiency objects
-  // tool->setProperty("EfficiencyBCalibrations", "410000;410004;410006;410021");
-  // tool->setProperty("EfficiencyCCalibrations", "410000;410004;410006;410021");
-  // tool->setProperty("EfficiencyTCalibrations", "410000;410004;410006;410021");
-  // tool->setProperty("EfficiencyLightCalibrations", "410000;410004;410006;410021");
-  // tool->setProperty("EigenvectorReductionB", "Medium");
-  // tool->setProperty("EigenvectorReductionC", "Medium");
-  // tool->setProperty("EigenvectorReductionLight", "Medium");
-  // specify that the file is to be looked for in the PathResolver "development" area (don't use this for official productions)
-  // tool->setProperty("UseDevelopmentFile",  true);
-  // specify the use of the cone-based labelling rather than the ghost association
-  code = tool->setProperty("ConeFlavourLabel", true);
-  if (code != StatusCode::SUCCESS) std::cout << "error setting BTaggingEfficiencyTool ConeFlavourLabel property" << std::endl;
-  // uncomment this to use the Run-1 style cone labelling (parton based, inclusive) instead of the Run-2 default (hadron based, exclusive)
-  // tool->setProperty("OldConeFlavourLabel", true);
+  // tool.setProperty("EigenvectorReductionB", "Medium");
+  // tool.setProperty("EigenvectorReductionC", "Medium");
+  // tool.setProperty("EigenvectorReductionLight", "Medium");
+  
   // uncomment this if the "Envelope" systematics model is to be used instead of the eigenvector variations
-  // tool->setProperty("SystematicsStrategy", "Envelope");
-  // A successful initialisation ought to be checked for
-  code = tool->initialize();
-  if (code != StatusCode::SUCCESS) {
-    std::cout << "Initialization of tool " << tool->name() << " failed! Subsequent results may not make sense." << std::endl;
+  // code = tool.setProperty("SystematicsStrategy", "Envelope");
+
+  StatusCode code6 = tool.initialize();
+
+  if (code1 != StatusCode::SUCCESS || code2 != StatusCode::SUCCESS || code3 != StatusCode::SUCCESS || code4 != StatusCode::SUCCESS 
+    || code5 != StatusCode::SUCCESS 
+    || code6 != StatusCode::SUCCESS) {
+    std::cout << "Initialization of tool " << tool->name() << " failed! " << std::endl;
+    return -1;
+  }
+  else {
+    std::cout << "Initialization of tool " << tool->name() << " finished." << std::endl;
   }
 
+
+  // select your efficiency map based on the DSID of your sample:
+  unsigned int sample_dsid = 410470;
+
+  tool->setMapIndex(sample_dsid);
+
+
   std::cout << "-----------------------------------------------------" << std::endl;
   const std::map<CP::SystematicVariation, std::vector<std::string> > allowed_variations = tool->listSystematics();
   std::cout << "Allowed systematics variations for tool " << tool->name() << ":" << std::endl;
@@ -68,80 +70,35 @@ int main() {
     std::cout << std::endl;
   }
   std::cout << "-----------------------------------------------------" << std::endl;
+  
 
-  bool retval = true;
 
   std::cout << "Creating a jet" << std::endl;
-  xAOD::JetFourMom_t p4(25000.,0.7,0.3,1000.);
+  xAOD::JetFourMom_t p4(50000.,0.7,0.3,1000.);
 
   xAOD::Jet * jet = new xAOD::Jet();
   jet->makePrivateStore();
   std::cout << "Setting jet 4 momentum" << std::endl;
   jet->setJetP4(p4);
   std::cout << "Setting jet attribute" << std::endl;
-  // light quark. Note that here and in the following, we fill both the Run-1 and Run-2 style flavour label variables
-  jet->setAttribute("ConeTruthLabelID", 0);
-  jet->setAttribute("HadronConeExclTruthLabelID", 0);
+  // b jet (label==5)
+  jet->setAttribute("HadronConeExclTruthLabelID", 5);
   float sf=0;
+  float eff=0;
   CorrectionCode result;
-  std::cout << "\nTesting function calls without systematics..." << std::endl;
-  result = tool->getEfficiency(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Light quark get efficiency failed"<<std::endl; retval=false;}
+  std::cout << "Testing function calls without systematics..." << std::endl;
+  result = tool->getEfficiency(*jet,eff);
+  if( result!=CorrectionCode::Ok) { std::cout << "b jet get efficiency failed"<<std::endl; retval=false;}
   else {
-    std::cout << "Light quark get efficiency succeeded: " << sf << std::endl;
+    std::cout << "b jet get efficiency succeeded: " << eff << std::endl;
   }
   result = tool->getScaleFactor(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Light quark get scale factor failed"<<std::endl; retval=false;}
+  if( result!=CorrectionCode::Ok) { std::cout << "b jet get scale factor failed"<<std::endl; retval=false;}
   else {
-    std::cout << "Light quark get scale factor succeeded: " << sf << std::endl;
+    std::cout << "b jet get scale factor succeeded: " << sf << std::endl;
   }
 
-  jet->setAttribute("ConeTruthLabelID", 5);
-  jet->setAttribute("HadronConeExclTruthLabelID", 5);
-  sf=0;
-  result = tool->getEfficiency(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Bottom quark get efficiency failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Bottom quark get efficiency succeeded: " << sf << std::endl;
-  }
-  result = tool->getScaleFactor(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Bottom quark get scale factor failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Bottom quark get scale factor succeeded: " << sf << std::endl;
-  }
-
-  jet->setAttribute("ConeTruthLabelID", 4);
-  jet->setAttribute("HadronConeExclTruthLabelID", 4);
-  sf=0;
-  result = tool->getEfficiency(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Charm quark get efficiency failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Charm quark get efficiency succeeded: " << sf << std::endl;
-  }
-  result = tool->getScaleFactor(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Charm quark get scale factor failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Charm quark get scale factor succeeded: " << sf << std::endl;
-  }
-
-  jet->setAttribute("ConeTruthLabelID", 15);
-  jet->setAttribute("HadronConeExclTruthLabelID", 15);
-  sf=0;
-  result = tool->getEfficiency(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Tau quark get efficiency failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Tau quark get efficiency succeeded: " << sf << std::endl;
-  }
-  result = tool->getScaleFactor(*jet,sf);
-  if( result!=CorrectionCode::Ok) { std::cout << "Tau quark get scale factor failed"<<std::endl; retval=false;}
-  else {
-    std::cout << "Tau quark get scale factor succeeded: " << sf << std::endl;
-  }
-
-  // systematics interface
-  jet->setAttribute("ConeTruthLabelID", 5);
-  jet->setAttribute("HadronConeExclTruthLabelID", 5);
-  std::cout << "\nTesting application of systematics to b jets..." << std::endl;
+  std::cout << "Testing function calls with systematics..." << std::endl;
   CP::SystematicSet systs = tool->affectingSystematics();
   for( CP::SystematicSet::const_iterator iter = systs.begin();
        iter!=systs.end(); ++iter) {
@@ -151,7 +108,7 @@ int main() {
     SystematicCode sresult = tool->applySystematicVariation(set);
     if( sresult !=SystematicCode::Ok) {
       std::cout << var.name() << " apply systematic variation FAILED " << std::endl;
-	}
+  }
     result = tool->getScaleFactor(*jet,sf);
     if( result!=CorrectionCode::Ok) {
       std::cout << var.name() << " getScaleFactor FAILED" << std::endl;
@@ -165,68 +122,7 @@ int main() {
   if (dummyResult != SystematicCode::Ok)
     std::cout << "problem disabling systematics setting!" << std::endl;
 
-  // out-of-bounds tests:
-  // (1) b jet outside the calibration range (300 GeV, at present) but inside the extrapolation range
-  xAOD::JetFourMom_t p4Extrapolated(500000.,0.7,0.3,1000.);
-  xAOD::Jet* extrapolatedJet = new xAOD::Jet;
-  extrapolatedJet->makePrivateStore();
-  std::cout << "\nSetting jet 4 momentum for b jet outside calibration but inside extrapolation range" << std::endl;
-  extrapolatedJet->setJetP4(p4Extrapolated);
-  extrapolatedJet->setAttribute("ConeTruthLabelID", 5);
-  extrapolatedJet->setAttribute("HadronConeExclTruthLabelID", 5);
-  result = tool->getScaleFactor(*extrapolatedJet,sf);
-  switch (result) {
-  case CorrectionCode::Error:
-    std::cout << "extrapolated b-jet get scale factor failed" << std::endl; break;
-  case CorrectionCode::OutOfValidityRange:
-    std::cout << "extrapolated b-jet get scale factor should not be flagged as out-of-validity!" << std::endl; break;
-  case CorrectionCode::Ok:
-    std::cout << "extrapolated b-jet get scale factor OK" << std::endl; break;
-  default:
-    break;
-  }
-  // (2) b jet outside the extrapolation range (3000 GeV, at present)
-  xAOD::JetFourMom_t p4Invalid(4000000.,0.7,0.3,1000.);
-  xAOD::Jet* invalidJet = new xAOD::Jet;
-  invalidJet->makePrivateStore();
-  std::cout << "\nSetting jet 4 momentum for b jet outside extrapolation range" << std::endl;
-  invalidJet->setJetP4(p4Invalid);
-  invalidJet->setAttribute("ConeTruthLabelID", 5);
-  invalidJet->setAttribute("HadronConeExclTruthLabelID", 5);
-  result = tool->getScaleFactor(*invalidJet,sf);
-  if (result != CorrectionCode::OutOfValidityRange) {
-    std::cout << "invalid b-jet get scale factor should have been flagged as out-of-validity but is not!" << std::endl;
-  } else {
-    std::cout << "invalid b-jet get scale factor correctly flagged as out-of-validity" << std::endl;
-  }
 
-  // test tool copying
-
-  // BTaggingEfficiencyTool* copiedTool = new BTaggingEfficiencyTool(*tool);
-  // std::cout << "-----------------------------------------------------" << std::endl;
-  // const std::map<CP::SystematicVariation, std::vector<std::string> > copied_variations = copiedTool->listSystematics();
-  // std::cout << "Allowed systematics variations for tool " << copiedTool->name() << ":" << std::endl;
-  // for (auto var : copied_variations) {
-  //   std::cout << std::setw(40) << std::left << var.first.name() << ":";
-  //   for (auto flv : var.second) std::cout << " " << flv;
-  //   std::cout << std::endl;
-  // }
-  // std::cout << "-----------------------------------------------------" << std::endl;
-  // sf=0;
-  // result = copiedTool->getEfficiency(*jet,sf);
-  // if( result!=CorrectionCode::Ok) { std::cout << "Bottom quark get efficiency failed"<<std::endl; retval=false;}
-  // else {
-  //   std::cout << "Bottom quark get efficiency succeeded: " << sf << std::endl;
-  // }
-  // result = copiedTool->getScaleFactor(*jet,sf);
-  // if( result!=CorrectionCode::Ok) { std::cout << "Bottom quark get scale factor failed"<<std::endl; retval=false;}
-  // else {
-  //   std::cout << "Bottom quark get scale factor succeeded: " << sf << std::endl;
-  // }
-
-
-  // release our resources
-  delete tool;
 
   return retval;
 }
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEigenVectorRecompositionToolTester.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEigenVectorRecompositionToolTester.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5b7ef7f2ca946dfe18bb577ce13f97c451e9136e
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingEigenVectorRecompositionToolTester.cxx
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include <AsgTools/AnaToolHandle.h>
+#include <AsgTools/ToolHandle.h>
+#include "FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h"
+#include "FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h"
+
+
+int main() {
+  bool retval = true;
+
+  std::string taggerName = "MV2c10";
+  std::string workingPointName = "Continuous";
+  
+  asg::AnaToolHandle<IBTaggingEfficiencyTool> btag_eff_tool("BTaggingEfficiencyTool/BTagEffTest");
+  StatusCode code1 = btag_eff_tool.setProperty("ScaleFactorFileName","xAODBTaggingEfficiency/13TeV/2017-21-13TeV-MC16-CDI-2019-07-30_v1.root" );
+  StatusCode code2 = btag_eff_tool.setProperty("TaggerName",    taggerName  );
+  StatusCode code3 = btag_eff_tool.setProperty("OperatingPoint", workingPointName);
+  StatusCode code4 = btag_eff_tool.setProperty("JetAuthor", "AntiKt4EMTopoJets" );
+  StatusCode code5 = btag_eff_tool.setProperty("MinPt", 20. );
+  // Exclude certain original uncertainties from Eigenvector scheme so that
+  // it these uncertainties will be exclude from eigen vector recomposition. 
+  // The original uncertainty names are separated by semicolon.
+  // Here exclude two uncertainties as an example.
+  // StatusCode code0 = btag_eff_tool.setProperty("ExcludeFromEigenVectorBTreatment","FT_EFF_PDF4LHC_np_19;JET_EffectiveNP_Mixed3");
+  StatusCode code6 = btag_eff_tool.initialize();
+  if (code1 != StatusCode::SUCCESS 
+      || code2 != StatusCode::SUCCESS 
+      || code3 != StatusCode::SUCCESS 
+      || code4 != StatusCode::SUCCESS 
+      || code5 != StatusCode::SUCCESS 
+      || code6 != StatusCode::SUCCESS ){
+    std::cout << "Initialization of tool " << btag_eff_tool->name() << " failed! " << std::endl;
+    return -1;
+  }
+  else {
+    std::cout << "Initialization of tool " << btag_eff_tool->name() << " finished." << std::endl;
+  } 
+
+  asg::AnaToolHandle<IBTaggingEigenVectorRecompositionTool> evr_tool("BTaggingEigenVectorRecompositionTool/BTagEVRTest");
+  StatusCode code7 = evr_tool.setProperty("BTaggingEfficiencyTool", btag_eff_tool);
+  StatusCode code8 = evr_tool.initialize();
+  if (code7 != StatusCode::SUCCESS
+      ||code8 != StatusCode::SUCCESS ) {
+    std::cout << "Initialization of tool" << evr_tool->name() << " failed!" << std::endl;
+  } else {
+    std::cout << "Initialization of tool " << evr_tool->name() << " finished." << std::endl;
+  }
+  
+  const std::string label = "B";
+  const unsigned int evIdx = 0;
+
+  /**
+     getCoefficientMap(label, EigenIdxList)
+     
+     input value:
+     1. label: falvor label in std::string format, could be one of B, C, T, Light
+     2. EigenIdxList is user defined vector containing all eigenvector index
+     that user interested in.
+     output:
+     Map of format map<string, map<string, float>> containing decomposition
+     coefficient of the list of eigenvectors defined by EigenIdxList.
+  */
+  std::vector<unsigned int> eigenIdxList = {1,2,3,4,5};
+  std::map<std::string, std::map<std::string, float>> coefficientMap = evr_tool->getCoefficientMap(label, eigenIdxList);
+
+  /**
+     getCoefficients(label, evIdx)
+     
+     input value:
+     1. label: falvor label in std::string format, could be one of B, C, T, Light
+     2. evIdx: The index of eigenvector user interested in.
+     output value:
+     vector of coefficient values. The order is the same as output given by
+     getListOfOriginalNuisanceParameters()
+   */
+  std::vector<float> coeffs = evr_tool->getCoefficients(label, evIdx);
+  
+  /**
+     getListOfOriginalNuisanceParameters(label)
+     
+     input value:
+     1. label: falvor label in std::string format, could be one of B, C, T, Light
+     output value:
+     List of original nuisance parameter names.
+   */
+  std::vector<std::string> orig_nps = evr_tool->getListOfOriginalNuisanceParameters(label);
+
+  /**
+     getNumEigenVectors(label)
+     
+     input value:
+     1. label: falvor label in std::string format, could be one of B, C, T, Light
+     return value:
+     number of eigen vectors used for chosen label. Return 0 if error occured. 
+   */
+  int nEigen = evr_tool->getNumEigenVectors("B");
+  if (nEigen >= 0){
+    std::cout<<"There are "<<nEigen
+	     <<" eigen vectors for flavour B."<<std::endl;
+  }
+
+  return retval;
+
+}
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingSelectionToolTester.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingSelectionToolTester.cxx
index d4a739656cbfa36935f6bdc3e5d35682b268323e..4df275359d44231dd1689e25cab6f38cd97d988a 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingSelectionToolTester.cxx
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingSelectionToolTester.cxx
@@ -2,80 +2,230 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"
-
+#ifdef XAOD_STANDALONE
+#include "xAODRootAccess/TEvent.h"
+#else
+#include "POOLRootAccess/TEvent.h"
+#endif
+#include <AsgTools/AnaToolHandle.h>
+#include "FTagAnalysisInterfaces/IBTaggingSelectionTool.h"
+
+#include "PATInterfaces/CorrectionCode.h"
 #include "xAODJet/JetAuxContainer.h"
 #include "xAODJet/JetContainer.h"
 #include "xAODBTagging/BTaggingAuxContainer.h"
+#include "xAODBTagging/BTagging.h"
+#include "xAODBTagging/BTaggingUtilities.h"
+
 
-#include "AsgMessaging/MessageCheck.h"
 
 #include <string>
 #include <iomanip>
+#include "TFile.h"
+
+using CP::CorrectionCode;
 
 int main() {
 
-  using namespace asg::msgUserCode;
-  ANA_CHECK_SET_TYPE (int);
 
-  BTaggingSelectionTool * tool = new BTaggingSelectionTool("BTagSelecTest");
-  ANA_CHECK (tool->setProperty( "MaxEta", 2.5 ));
-  ANA_CHECK (tool->setProperty( "MinPt", 20000. ));  
-  //  ANA_CHECK (tool->setProperty( "FlvTagCutDefinitionsFileName","xAODBTaggingEfficiency/13TeV/2016-20_7-13TeV-MC15-CDI-May31_v1.root" ));
-  ANA_CHECK (tool->setProperty( "FlvTagCutDefinitionsFileName","xAODBTaggingEfficiency/share/AntiKt2TrackJets_20160615.root" ));
-  ANA_CHECK (tool->setProperty("TaggerName",     "MV2c00_MV2c100"  ));
-  ANA_CHECK (tool->setProperty("OperatingPoint", "2DFixedCutBEff_85"   ));
-  ANA_CHECK (tool->setProperty("JetAuthor",      "AntiKt2PV0TrackJets" ));
+  std::string taggerName = "DL1";
+  std::string workingPointName = "HybBEff_77";
 
+
+  asg::AnaToolHandle<IBTaggingSelectionTool> tool("BTaggingSelectionTool/BTagSelecTest");
+  StatusCode code1 = tool.setProperty( "FlvTagCutDefinitionsFileName","xAODBTaggingEfficiency/13TeV/2017-21-13TeV-MC16-CDI-2018-02-09_v1.root" );
+  StatusCode code2 = tool.setProperty("TaggerName",    taggerName  );
+  StatusCode code3 = tool.setProperty("OperatingPoint", workingPointName);
+  StatusCode code4 = tool.setProperty("JetAuthor",      "AntiKt4EMTopoJets" );
   // A successful initialisation ought to be checked for
-  StatusCode code = tool->initialize();
-  if (code != StatusCode::SUCCESS) {
-    std::cout << "Initialization of tool " << tool->name() << " failed! Subsequent results may not make sense." << std::endl;
+  StatusCode code5 = tool.initialize();
+
+  if (code1 != StatusCode::SUCCESS || code2 != StatusCode::SUCCESS || code3 != StatusCode::SUCCESS || code4 != StatusCode::SUCCESS || code5 != StatusCode::SUCCESS) {
+    std::cout << "Initialization of tool " << tool->name() << " failed! " << std::endl;
+    return -1;
   }
   else {
     std::cout << "Initialization of tool " << tool->name() << " finished." << std::endl;
   }
 
-  bool retval = true;
 
-  std::cout << "\nTesting function calls for a large pT range..." << std::endl;
-  for (unsigned pt=15000; pt<1200000; pt+=100000){
-    if (tool->accept(pt, 0.5, 0.5543, 0.)){
-      std::cout << "Jet is tagged" << std::endl;
-    } else {
-      std::cout << "Jet is untagged" << std::endl;
+  //load some jets to show how to use the tool
+
+  //  xAOD::TEvent event;
+  #ifdef XAOD_STANDALONE
+  xAOD::TEvent event(xAOD::TEvent::kClassAccess);
+  #else
+  POOL::TEvent event(POOL::TEvent::kClassAccess);
+  #endif
+
+
+  TFile* m_file = TFile::Open("/afs/cern.ch/work/j/jshlomi/public/DAOD_FTAG2.root","read");
+
+  if(!event.readFrom(m_file).isSuccess()){ std::cout << "failed to load file" << std::endl; return -1; }
+
+  event.getEntry(0);
+
+  const xAOD::JetContainer* jets = 0;
+
+  if (!event.retrieve( jets, "AntiKt4EMTopoJets" ).isSuccess() ){ std::cout << " error retrieving jets " << std::endl; return -1;}
+
+  int jet_index = 0;
+  for (const xAOD::Jet* jet : *jets) {
+
+    //getting a tagging decision, is the jet tagged or not
+    bool tagged = static_cast<bool>(tool->accept(*jet));
+
+    //you can get the tagger weight,
+    double tagweight;
+    if( tool->getTaggerWeight( *jet ,tagweight)!=CorrectionCode::Ok ){ std::cout << " error retrieving tagger weight " << std::endl; return -1; }
+
+    std::cout << "jet " << jet_index << " " <<  taggerName  << "  " << workingPointName << " is tagged " << tagged << " tag weight " << tagweight << std::endl;
+
+
+
+
+    //if you have DL1 weights, you can get the tagger weight this way
+    const xAOD::BTagging *btag = xAOD::BTaggingUtilities::getBTagging( *jet );
+
+    double dl1_pb = btag->auxdata<double>("DL1_pb");
+    double dl1_pc = btag->auxdata<double>("DL1_pc");
+    double dl1_pu = btag->auxdata<double>("DL1_pu");
+
+
+    if(  tool->getTaggerWeight(dl1_pb,dl1_pc,dl1_pu, tagweight) !=CorrectionCode::Ok ){ std::cout << " error retrieving tagger weight " << std::endl; return -1; }
+
+    std::cout << " tagweight " << tagweight << std::endl;
+
+    double pT = jet->pt();
+    double eta = jet->eta();
+
+    // you can see if the jet is tagged using its pt/eta and tagweight
+
+    tagged = static_cast<bool>(tool->accept(pT,eta,tagweight));
+
+    //you can also extract the cut value (which may or may not depend on the jet pt)
+
+    double cutval;
+     //provide the pt in MeV
+    if( tool->getCutValue( jet->pt() , cutval)!=CorrectionCode::Ok ){ std::cout << " error retrieving cut value " << std::endl; return -1; }
+
+    std::cout << " tagged " << tagged << " cut value " << cutval << std::endl;
+
+    jet_index++;
+
+  }
+
+  //Continuous working points
+  //*************************
+  //with a selection tool using the Continuous working point,
+  //you can get the jets tag weight bin (between the different fixedcutBEff working points, 60,70,77,85)
+  taggerName = "DL1";
+  workingPointName = "Continuous";
+  asg::AnaToolHandle<IBTaggingSelectionTool> tool_Continuous("BTaggingSelectionTool/BTagSelContinuousTest");
+  code1 = tool_Continuous.setProperty( "FlvTagCutDefinitionsFileName","xAODBTaggingEfficiency/13TeV/2017-21-13TeV-MC16-CDI-2018-02-09_v1.root" );
+  code2 = tool_Continuous.setProperty("TaggerName",    taggerName  );
+  code3 = tool_Continuous.setProperty("OperatingPoint", workingPointName );
+  code4 = tool_Continuous.setProperty("JetAuthor",      "AntiKt4EMTopoJets" );
+  code5 = tool_Continuous.initialize();
+
+  if (code1 != StatusCode::SUCCESS || code2 != StatusCode::SUCCESS || code3 != StatusCode::SUCCESS || code4 != StatusCode::SUCCESS || code5 != StatusCode::SUCCESS) {
+    std::cout << "Initialization of tool " << tool_Continuous->name() << " failed! " << std::endl;
+    return -1;
+  }
+  else {
+    std::cout << "Initialization of tool " << tool_Continuous->name() << " finished." << std::endl;
+  }
+
+  jet_index = 0;
+  for (const xAOD::Jet* jet : *jets) {
+
+    double tagweight;
+    if( tool->getTaggerWeight( *jet ,tagweight)!=CorrectionCode::Ok ){ 
+      std::cout << " error retrieving tagger weight " << std::endl; return -1; 
     }
+    int quantile = tool_Continuous->getQuantile(*jet);
+    
+
+    std::cout << "jet " << jet_index << " " <<  taggerName  << "  " << workingPointName << " tag weight " << tagweight <<  " quantile " << quantile << std::endl;
+
+    jet_index++;
+
   }
 
-  // #### Trying to build a b-jet on the fly
-  // auto JetAuxContainer = new xAOD::JetAuxContainer();
-  // auto JetContainer = new xAOD::JetContainer();
-  // JetContainer->setStore(JetAuxContainer);
-  // auto tjet = new xAOD::Jet();
-  // JetContainer->push_back(tjet);
-
-  // std::cout << "jet container ready, now btagging ones" << std::endl;
-
-  // auto BTaggingAuxContainer = new xAOD::BTaggingAuxContainer();
-  // auto BTaggingContainer = new xAOD::BTaggingContainer();
-  // BTaggingContainer->setStore(BTaggingAuxContainer);
-  // auto BTagging = new xAOD::BTagging();
-  // BTaggingContainer->push_back(BTagging);
-
-  // std::cout << "BTagging container ready, now the store" << std::endl;
-  // xAOD::TStore store;
-  // store.record(JetContainer, "JetTest");
-  // store.record(JetAuxContainer, "JetTestAux.");
-  // store.record(BTaggingContainer, "BTagTest");
-  // store.record(BTaggingAuxContainer, "BTagTestAux.");
-  // std::cout << "Store ready" << std::endl;
-  // std::cout << tjet << "\t\t" << BTaggingContainer << "\t\t" << BTagging << std::endl;
-
-  // ElementLink< xAOD::BTaggingContainer> linkBTagger;
-  // linkBTagger.toContainedElement(*BTaggingContainer, BTagging);
-  // // tjet->setBTaggingLink(linkBTagger);
-  // // BTagging->setVariable("MV2c20", "discriminant", 0.20);
-  // ######
-
-  return retval;
+
+  //Veto working points
+  //**************************
+  //by setting the OperatingPoint to a string with the format WP1_Veto_Tagger2_WP2
+  //for example, FixedCutBEff_70_Veto_DL1_CTag_Loose
+  //the selection tool will require the jet to be
+  //tagged by the standard working point
+  //and to not be tagged by the secondary tagger and working point
+
+  taggerName = "MV2c10";
+  workingPointName = "FixedCutBEff_70_Veto_DL1_CTag_Loose";
+
+  asg::AnaToolHandle<IBTaggingSelectionTool> tool_veto("BTaggingSelectionTool/BTagSelecVetoTest");
+  code1 = tool_veto.setProperty( "FlvTagCutDefinitionsFileName","xAODBTaggingEfficiency/13TeV/2017-21-13TeV-MC16-CDI-2018-02-09_v1.root" );
+  code2 = tool_veto.setProperty("TaggerName",    taggerName  );
+  code3 = tool_veto.setProperty("OperatingPoint", workingPointName );
+  code4 = tool_veto.setProperty("JetAuthor",      "AntiKt4EMTopoJets" );
+  code5 = tool_veto.initialize();
+
+  if (code1 != StatusCode::SUCCESS || code2 != StatusCode::SUCCESS || code3 != StatusCode::SUCCESS || code4 != StatusCode::SUCCESS || code5 != StatusCode::SUCCESS) {
+    std::cout << "Initialization of tool " << tool_veto->name() << " failed! " << std::endl;
+    return -1;
+  }
+  else {
+    std::cout << "Initialization of tool " << tool_veto->name() << " finished." << std::endl;
+  }
+
+
+  jet_index = 0;
+  for (const xAOD::Jet* jet : *jets) {
+
+    //getting a tagging decision, is the jet tagged or not
+    bool tagged = static_cast<bool>(tool_veto->accept(*jet));
+
+
+    // if you are using a format without xAOD::Jets or where the jet does not have a properly filled b-tagging object,
+    // you need the two tagger weights, for the nominal tagger and the veto tagger.
+
+    //you can get the tagger weight,
+    double tagweight_nominal;
+    double tagweight_veto_tagger;
+
+    if( tool_veto->getTaggerWeight( *jet ,tagweight_nominal)!=CorrectionCode::Ok ){ std::cout << " error retrieving nominal tagger weight " << std::endl; return -1; }
+    //use a third argument set to true to getTaggerWeight for the veto tagger weight
+    if( tool_veto->getTaggerWeight( *jet ,tagweight_veto_tagger,true)!=CorrectionCode::Ok ){ std::cout << " error retrieving veto tagger weight " << std::endl; return -1; }
+
+
+    //if you have DL1 weights, you can get the tagger weight this way
+    const xAOD::BTagging *btag = xAOD::BTaggingUtilities::getBTagging( *jet );
+
+    double dl1_pb = btag->auxdata<double>("DL1_pb");
+    double dl1_pc = btag->auxdata<double>("DL1_pc");
+    double dl1_pu = btag->auxdata<double>("DL1_pu");
+
+    //the 5th argument tells it to retrive the veto tagger weight
+    if(  tool_veto->getTaggerWeight(dl1_pb,dl1_pc,dl1_pu, tagweight_veto_tagger,true) !=CorrectionCode::Ok ){ std::cout << " error retrieving tagger weight " << std::endl; return -1; }
+
+
+
+    double pT = jet->pt();
+    double eta = jet->eta();
+
+    bool tagged_withtagweights = static_cast<bool>(tool_veto->accept(pT,eta,tagweight_nominal,tagweight_veto_tagger));
+
+
+    std::cout << "jet " << jet_index << " " <<  taggerName  << "  " << workingPointName << " is tagged " << tagged << " tagged (with tagweights) "<< tagged_withtagweights << std::endl;
+
+    jet_index++;
+
+  }
+
+
+
+
+
+  return 0;
 }
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingTruthTaggingTester.cxx b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingTruthTaggingTester.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..960db42f713b7deb485e8576330a3edbbd8ed5e9
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/util/BTaggingTruthTaggingTester.cxx
@@ -0,0 +1,99 @@
+#include "AsgTools/AsgTool.h"
+#include "AsgMessaging/MessageCheck.h"
+#include "AsgMessaging/MsgStream.h"
+#include <AsgTools/AnaToolHandle.h>
+#include "FTagAnalysisInterfaces/IBTaggingTruthTaggingTool.h"
+
+
+#include <string>
+#include <iomanip>
+#include <vector>
+
+int main() {
+
+  asg::AnaToolHandle<IBTaggingTruthTaggingTool> tool("BTaggingTruthTaggingTool/BtagTT_Tool");
+
+
+   //choose working point and CDI file
+   StatusCode code = tool.setProperty("TaggerName", "MV2c10");
+   StatusCode code2 = tool.setProperty("OperatingPoint", "FixedCutBEff_77");
+   StatusCode code3 = tool.setProperty("JetAuthor", "AntiKt4EMTopoJets");
+   StatusCode code4 = tool.setProperty("ScaleFactorFileName", "xAODBTaggingEfficiency/13TeV/2017-21-13TeV-MC16-CDI-2018-02-09_v1.root");
+
+
+   //truth tagging settings
+   StatusCode code5 = tool.setProperty("IgnoreScaleFactors", false); //use the data/MC and MC/MC scale factors when computing event weights
+   StatusCode code6 = tool.setProperty("UseSystematics", true); // store event weights for all systematic variations in the results object
+   StatusCode code7 = tool.setProperty("MaxNtagged", 3);
+   StatusCode code8 = tool.setProperty("UsePermutations", true);
+   StatusCode code9 = tool.setProperty("UseQuantile", true);
+
+   StatusCode code10 = tool.initialize();
+
+  if (code != StatusCode::SUCCESS || code2 != StatusCode::SUCCESS || code3 != StatusCode::SUCCESS || code4 != StatusCode::SUCCESS || code5 != StatusCode::SUCCESS ||
+    code6 != StatusCode::SUCCESS || code7 != StatusCode::SUCCESS || code8 != StatusCode::SUCCESS ||  code9 != StatusCode::SUCCESS || code10 != StatusCode::SUCCESS ) {
+    std::cout << "Initialization of tool " << tool->name() << " failed! " << std::endl;
+    return -1;
+  }
+  else {
+    std::cout << "Initialization of tool " << tool->name() << " finished." << std::endl;
+  }
+
+  //Set the jets to be used in the tool.
+  std::vector<double> pt = {44000., 66000., 77000.};
+  std::vector<double> eta = {2.2, 1.6, 1.7};
+  std::vector<int> flav = {0,4,5};
+  std::vector<double> tagw = {0.3, 0.55, 0.99};
+
+  Analysis::TruthTagResults results;
+
+  if(StatusCode::SUCCESS!=tool->CalculateResults( pt,eta,flav,tagw, results) ){
+    std::cout << "failed to compute truth tagging results! " << std::endl;
+    return -1;
+  };
+
+  //direct tagged results:
+  std::cout << "Direct tagged results:  "<< std::endl;
+  for(unsigned int i=0; i< results.is_tagged.size();i++)
+  {
+    std::cout << "jet "<< i << " is direct tagged: " << results.is_tagged.at(i) << std::endl;
+  }
+  //print the results for each of the systematic variations
+
+  for(unsigned int systindex=0; systindex< results.syst_names.size(); systindex++){
+      std::string syst_name = results.syst_names.at(systindex);
+
+      std::cout << "direct tag Event SF ( "<< syst_name  <<" ) = " <<results.getEvtDirectTagSF(syst_name) << std::endl;
+
+  }
+
+
+  //truth tagging results:
+  for(int ntags=1; ntags<=3;ntags++){
+
+    std::cout << " for " << ntags << " tagged jets: " << std::endl;
+    std::cout << " --------------------------------- " << std::endl;
+    //print chosen premutation, tagweight bin assinment and event weight
+
+    std::vector<bool> exclusive_permuation = results.getEventPermutation(ntags,true);
+    std::vector<int> exclusive_tagweightBin = results.getEventQuantiles(ntags,true);
+
+    std::vector<bool> inclusive_permuation = results.getEventPermutation(ntags,false);
+    std::vector<int> inclusive_tagweightBin = results.getEventQuantiles(ntags,false);
+
+    std::cout << "        exclusive    ||      inclusive" << std::endl;
+    std::cout << "      tagged | bin   ||    tagged | bin" << std::endl;
+    for(unsigned int i=0; i< exclusive_permuation.size();i++)
+      {
+        std::cout << "jet "<< i << "       " << exclusive_permuation.at(i) << " " << exclusive_tagweightBin.at(i)
+         << "      ||          " <<  inclusive_permuation.at(i) << " " << inclusive_tagweightBin.at(i) << std::endl;
+      }
+
+    std::cout << " Nominal event weight exclusive: " << results.getEventWeight(ntags,true,"Nominal") << std::endl;
+    std::cout << " Nominal event weight inclusive: " << results.getEventWeight(ntags,false,"Nominal") << std::endl;
+    std::cout << " ---------------------------------\n\n " << std::endl;
+
+  }
+
+  return 0;
+}
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEfficiencyTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEfficiencyTool.h
index 0a1e9b595d4447bceef93e04fa6cf8cc53e33569..08daa349783d8147662c9a5ec6f56d722397582f 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEfficiencyTool.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEfficiencyTool.h
@@ -1,7 +1,7 @@
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -196,6 +196,20 @@ class BTaggingEfficiencyTool: public asg::AsgTool,
   std::map<std::string, std::vector<std::string> > listScaleFactorSystematics(bool named = false) const;
   /// @}
 
+  /**
+   * Run EigenvectorRecomposition method and get the coefficient map.
+   * Calling EigenVectorRecomposition method in CDI and retrieve recomposition map.
+   * If success, coefficientMap would be filled and return ok.
+   * If failed, return error.
+   * label  :  flavour label
+   * coefficientMap: store returned coefficient map. This map could help expressing eigenvector NPs by linear
+   * combination of original uncertainty NPs in workspace level of physics analysis. The coefficient value
+   * is stored in the map in the format of:
+   * map<"Eigen_B_0", map<"[original uncertainty name]", [corresponding coefficient value]>> 
+   */
+  CP::CorrectionCode getEigenRecompositionCoefficientMap(const std::string &label, std::map<std::string, std::map<std::string, float>> & coefficientMap);
+  /// @}
+
 private:
 
   struct SystInfo {
@@ -344,7 +358,6 @@ private:
   /// actual information identifying efficiency calibration objects
   std::map<unsigned int, unsigned int> m_EffIndices;
 
-
   //cache for efficiency map config file that maps from a sample DSID to the correct efficiency map
   std::map<unsigned int, unsigned int> m_DSID_to_MapIndex;
   /// @}
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e8b1f2084343ab4685e17ae4d54d65d8ae85fe5
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h
@@ -0,0 +1,130 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// BTaggingEigenVectorRecomposition.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+/**
+@class BTaggingEigenVectorRecompositionTool
+Tool to help retrieving(from CDI) and providing coefficents values which
+could be used for expressing eigen vector NPs by linear combination of
+original uncertainty NPs in workspace level of the physics analysis.
+Then eigenvector uncertainties are replaced by original uncertainties.
+Replacement could help us correlate uncertainties between analyses
+which are using different tagger algorighthms.
+@author Y. Ke, Q. Buat
+@contact yake@cern.ch, qbuat@cern.ch
+**/
+#ifndef CPBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
+#define CPBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
+
+#include "FTagAnalysisInterfaces/IBTaggingEigenVectorRecompositionTool.h"
+#include "FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h"
+#include "PATInterfaces/ISystematicsTool.h"
+#include "PATInterfaces/SystematicCode.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "AsgTools/AsgTool.h"
+#include "AsgTools/ToolHandle.h"
+#include "AsgTools/AnaToolHandle.h"
+
+class BTaggingEigenVectorRecompositionTool: public asg::AsgTool,
+            public virtual IBTaggingEigenVectorRecompositionTool
+{
+  /// Create a proper constructor for Athena
+  ASG_TOOL_CLASS2( BTaggingEigenVectorRecompositionTool, IBTaggingEigenVectorRecompositionTool, ISystematicsTool)
+
+  public:
+
+
+  /// Create a constructor for standalone usage
+  BTaggingEigenVectorRecompositionTool( const std::string& name );
+
+  /// Create a constructor for standalone usage
+  virtual ~BTaggingEigenVectorRecompositionTool();
+
+  /**
+   * Return a vector which contains a list of original vector uncertainties names.
+   * vector list is for the chosen flavour label. The order of the names is the same
+   * as the coefficient values given by getCoefficients()  
+   **/
+  std::vector<std::string> getListOfOriginalNuisanceParameters(const std::string& label) const;
+  
+  /**
+   * Produce a coefficient map contains only eigenvectors that is showing in
+   * eigenIdxList and return it to user. If given empty evIdxList, the function
+   * returns a full map. Produced map is for the chosen flavour label.
+   **/
+   std::map<std::string, std::map<std::string, float>> getCoefficientMap(const std::string & label,
+									 const std::vector<unsigned int> eigenIdxList = 
+									 std::vector<unsigned int>()) const;
+
+  /**
+   * Returns a vector contains the coefficients value of the chosen label
+   * and the chosen eigenvector. The order of the value is the same as
+   * the order of original uncertainty names given by
+   * getListOfOriginalNuisanceParameters()
+   **/
+  std::vector<float> getCoefficients(const std::string & label, const unsigned int evIdx) const;
+
+  // Return number of eigenvectors used for the chosen label.
+  int getNumEigenVectors(const std::string & label)const;
+
+  /**
+   * Initialize BtaggingEfficiencyTool handle and retrieve coefficient map for
+   * all flavours. Also initialize vectors which contains all original sources
+   * uncertainties' names. One vector for each flavour.
+   **/  
+  StatusCode initialize();
+
+  // this returns a list of systematics supported by the btaggingEfficiency tool handle
+  CP::SystematicSet affectingSystematics() const;
+
+  /** it indicates which systematic shifts are to be applied for all future calls
+   * no systematics for now, proxy for later
+   **/
+  CP::SystematicCode applySystematicVariation( const CP::SystematicSet & systConfig);
+
+  /**
+   * subset of systematics that are recommended by the
+   * btaggingEfficiency tool handle
+   **/
+  CP::SystematicSet recommendedSystematics() const;
+
+  /**
+   * returns true if the argument systematic is supported by the
+   * btaggingEfficiency tool handle
+   **/
+  bool isAffectedBySystematic( const CP::SystematicVariation & systematic ) const;
+
+
+ private:
+
+  // memeber variable maps which has format:
+  // map<"Eigen_[flavour]_[index]", map<"[original uncertainty name]", coefficent value>
+  // One map for each flavour.
+  std::map<std::string, std::map<std::string, float>> m_coefficientMapB;
+  std::map<std::string, std::map<std::string, float>> m_coefficientMapC;
+  std::map<std::string, std::map<std::string, float>> m_coefficientMapT;
+  std::map<std::string, std::map<std::string, float>> m_coefficientMapLight;
+
+  // contains list of original uncertainty names. The aim for having this
+  // is to keep the order of uncertainty names.
+  // One list for each flavour.
+  std::vector<std::string> m_NPnameListB;
+  std::vector<std::string> m_NPnameListC;
+  std::vector<std::string> m_NPnameListT;
+  std::vector<std::string> m_NPnameListLight;
+
+  // BtaggingEfficiencyTool handle.
+  ToolHandle<IBTaggingEfficiencyTool> m_btageffTool;
+
+};
+
+#endif // CPBTAGGINGEIGENVECTORRECOMPOSITIONTOOL_H
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingSelectionTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingSelectionTool.h
index 3f9fc8f3eb5cc163af40af8c51512e50da72b3a8..b57be79b68e07815770108486bc2002c45912af2 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingSelectionTool.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingSelectionTool.h
@@ -1,8 +1,7 @@
-
 // Dear emacs, this is -*- c++ -*-
 
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -44,7 +43,7 @@ class BTaggingSelectionTool: public asg::AsgTool,
   /// Create a constructor for standalone usage
   BTaggingSelectionTool( const std::string& name );
   StatusCode initialize() override;
-  
+
   /// Get the decision using a generic IParticle pointer
   virtual asg::AcceptData accept( const xAOD::IParticle* p ) const override;
   virtual asg::AcceptData accept( const xAOD::Jet& jet ) const override;
@@ -56,9 +55,9 @@ class BTaggingSelectionTool: public asg::AsgTool,
 
   /// Decide in which quantile of the MV2c20 weight distribution the jet belongs (continuous tagging)
   /// The return value represents the bin index of the quantile distribution
-  virtual int getQuantile( const xAOD::IParticle*) const override;
-  virtual int getQuantile( const xAOD::Jet&) const override;
-  virtual int getQuantile( double /* jet pt */, double /* jet eta */, double /* mv2c20 weight */) const override;
+  virtual int getQuantile( const xAOD::IParticle* ) const override;
+  virtual int getQuantile( const xAOD::Jet& ) const override;
+  virtual int getQuantile( double /* jet pt */, double /* jet eta */, double /* mv2c20 weight */  ) const override;
 
   virtual CP::CorrectionCode getCutValue(double /* jet pt */, double & cutval, bool useVetoWP = false) const override;
   virtual CP::CorrectionCode getTaggerWeight( const xAOD::Jet& jet, double & weight ,bool useVetoWP = false) const override;
@@ -67,13 +66,13 @@ class BTaggingSelectionTool: public asg::AsgTool,
   const asg::AcceptInfo& getAcceptInfo( ) const  override {return m_acceptinfo;} 
 private:
   /// Helper function that decides whether a jet belongs to the correct jet selection for b-tagging
-  virtual bool checkRange( double /* jet pt */, double /* jet eta */, asg::AcceptData& ) const;
+  virtual bool checkRange( double /* jet pt */, double /* jet eta */ , asg::AcceptData& ) const;
   //fill the spline or vector that store the cut values for a particular working point
   void InitializeTaggerVariables(std::string taggerName,std::string OP, TSpline3 *spline, TVector *constcut, double &fraction);
 
   bool m_initialised;
 
-  bool m_ErrorOnTagWeightFailure;
+	bool m_ErrorOnTagWeightFailure;
 
    /// Object used to store the last decision
   asg::AcceptInfo m_acceptinfo;
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0be22b4cb31a39bbd980d47ac0f7deff24a0009d
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h
@@ -0,0 +1,266 @@
+// Dear emacs, this is -*- c++ -*-
+///////////////////////////////////////////////////////////////////
+// BTaggingTruthTaggingTool.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+/**
+  @class BTaggingTruthTaggingTool
+  Tool to apply flavour-tagging requirements on jets
+  @author C. Rizzi, M. Ughetto
+  @contact chiara.rizzi@cern.ch, mughetto@cern.ch
+**/
+
+#ifndef CPBTAGGINGTRUTHTAGGINGTOOL_H
+#define CPBTAGGINGTRUTHTAGGINGTOOL_H
+
+#include "FTagAnalysisInterfaces/IBTaggingTruthTaggingTool.h"
+#include "xAODBTagging/BTagging.h"
+
+#include "AsgTools/AsgTool.h"
+#include "AsgMessaging/MessageCheck.h"
+
+#include "TFile.h"
+#include "TRandom3.h"
+#include "TVector.h"
+#include "TFile.h"
+#include <string>
+#include <vector>
+#include <map>
+
+// include xAODBtaggingEfficiency classes
+#include "FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h"
+#include "FTagAnalysisInterfaces/IBTaggingSelectionTool.h"
+#include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
+#include "AsgTools/AnaToolHandle.h"
+
+// calibration data variable
+#include "CalibrationDataInterface/CalibrationDataVariables.h"
+#include "xAODBTaggingEfficiency/TruthTagResults.h"
+
+// xAOD jet
+#include "xAODJet/JetContainer.h"
+
+class BTaggingTruthTaggingTool: public asg::AsgTool,
+        public virtual IBTaggingTruthTaggingTool {
+  //typedef double (xAOD::BTagging::* tagWeight_member_t)() const;
+
+  /// Create a proper constructor for Athena
+  ASG_TOOL_CLASS2( BTaggingTruthTaggingTool , IBTaggingTruthTaggingTool, ISystematicsTool )
+
+    private:
+      struct jetVariable{
+      Analysis::CalibrationDataVariables vars;
+      int flav;
+    };
+
+    // all the results about a single event are stored in this object
+    struct TRFinfo {
+
+      std::vector<jetVariable> jets;
+      unsigned int njets;
+
+      TRandom3 rand;
+
+      std::vector<std::vector<bool> > perm_ex; // for each tag mult, vector of bool: is the i-th jet tagged or not?
+      std::vector<std::vector<bool> > perm_in;
+      std::vector<std::vector<double> > trfwsys_ex; // map between syst and vecot with truth-tag weights (pos = # of b-tags)
+      std::vector<std::vector<double> > trfwsys_in;
+      std::vector<std::vector<int> > tbins_ex; //for each tag mult, vector of int: quantile of each jet
+      std::vector<std::vector<int> > tbins_in;
+
+      std::vector<double> effMC; // map between syst and vector of eff*SF for each jet
+      std::vector<double> eff; // map between syst and vector of eff*SF for each jet
+
+      std::map<std::string,std::vector<double>> eff_allOP; // same but map for each OP
+      std::map<std::string,std::vector<double>> effMC_allOP; // same but map for each OP
+      std::vector<double> permprob_ex; // probablity of chosen perm with nominal SF
+      std::vector<double> permprob_in;
+      std::vector<double> binsprob_ex; // probability of chosen quantile with nominal SF
+      std::vector<double> binsprob_in;
+
+      std::map<int,std::vector<std::vector<std::vector<bool> > > > perms;
+      std::vector<std::vector<double> > permsWeight;
+      std::vector<std::vector<double> > permsSumWeight;
+
+    };
+
+  public:
+  /// Create a constructor for standalone usage
+  BTaggingTruthTaggingTool( const std::string& name );
+
+  private:
+  StatusCode CalculateResults(TRFinfo &trfinf, Analysis::TruthTagResults& results,int rand_seed = -1);
+
+  public:
+  StatusCode CalculateResults( std::vector<double>& pt, std::vector<double>& eta, std::vector<int>& flav, std::vector<double>& tagw, Analysis::TruthTagResults& results,int rand_seed = -1);
+  StatusCode CalculateResults( const xAOD::JetContainer& jets, Analysis::TruthTagResults& results,int rand_seed = -1);
+  StatusCode setEffMapIndex(const std::string& flavour, unsigned int index);
+  void setUseSystematics(bool useSystematics);
+
+  virtual  ~BTaggingTruthTaggingTool();
+
+  StatusCode initialize();
+
+  CP::SystematicSet affectingSystematics() const;
+  CP::SystematicCode applySystematicVariation( const CP::SystematicSet & systConfig);
+  CP::SystematicSet recommendedSystematics() const;
+  bool isAffectedBySystematic( const CP::SystematicVariation & systematic ) const;
+
+
+  private:
+
+  // set the jets in the event (pass same jets that satisfy kinematic criteria for b-tagging in pT and eta)
+  StatusCode setJets(TRFinfo &trfinf,std::vector<double>& pt, std::vector<double>& eta, std::vector<int>& flav, std::vector<double>& tagw);
+  StatusCode setJets(TRFinfo &trfinf,const xAOD::JetContainer& jets);
+  StatusCode setJets(TRFinfo &trfinf,std::vector<int>& flav, std::vector<Analysis::CalibrationDataVariables>* vars);
+
+  // get truth tagging weights
+  // for one single systematic (including "Nominal")
+  StatusCode GetTruthTagWeights(TRFinfo &trfinf, std::vector<double> &trf_weight_ex, std::vector<double> &trf_weight_in, int sys=0);
+
+  // tag permutation: trf_chosen_perm_ex.at(ntag).at(i) tells if the i-th jet is tagged in a selection requiring == ntag tags
+  StatusCode getTagPermutation(TRFinfo &trfinf, std::vector<std::vector<bool> > &trf_chosen_perm_ex, std::vector<std::vector<bool> > &trf_chosen_perm_in);
+
+  // chosen quantile: trf_bin_ex.at(ntag).at(i) tells the quantile in which the i-th jet falls in a selection requiring == ntag tags
+  // returns 5 if between 60% and 0%
+  // returns 4 if between 70% and 60%
+  // returns 3 if between 77% and 70%
+  // returns 2 if between 85% and 77%
+  // returns 1 if between 100% and 85%
+  // returns 0 if smaller than -1e4-> should never happen --> not currently implemented
+  // return -1 if bigger than 1e4 or not in b-tagging acceptance --> not currently implemented
+  StatusCode getQuantiles(TRFinfo &trfinf,std::vector<std::vector<int> > &trf_bin_ex, std::vector<std::vector<int> > &trf_bin_in);
+
+  // functions to make comparison with direct-tagging easier
+  double getEvtSF(TRFinfo &trfinf,int syst=0);
+  StatusCode getDirectTaggedJets(TRFinfo &trfinf,std::vector<bool> &is_tagged);
+
+  //These WP must be listed in ascending order of cut value, meaning 85 to 60
+  std::vector<std::string> m_availableOP_fixCut= {"FixedCutBEff_85", "FixedCutBEff_77","FixedCutBEff_70","FixedCutBEff_60"};
+  std::vector<std::string> m_availableOP_fixEff= {"FlatBEff_85", "FlatBEff_77", "FlatBEff_70", "FlatBEff_60"};
+  std::vector<std::string> m_availableOP_HybEff= {"HybBEff_85", "HybBEff_77", "HybBEff_70", "HybBEff_60"};
+  std::vector<std::string> m_availableOP;
+
+  //this vector gets filled automatically when you initialize the tool, and given to the user.
+  std::vector<float> m_binEdges = {};
+  TFile *m_inf; //file for reading the cut values from the CDI.
+
+  bool m_initialised;
+
+  StatusCode getTRFweight(TRFinfo &trfinf,unsigned int nbtag, bool isInclusive, int sys);
+  StatusCode getAllEffMC(TRFinfo &trfinf);
+  StatusCode getAllEffSF(TRFinfo &trfinf,int =0);
+  std::vector<CP::SystematicSet> m_eff_syst;
+  std::vector<std::string> m_sys_name;
+
+  // flav labelling
+  int jetFlavourLabel (const xAOD::Jet& jet);
+
+  int GAFinalHadronFlavourLabel(const xAOD::Jet& jet);
+  int ConeFinalPartonFlavourLabel (const xAOD::Jet& jet);
+  int ExclusiveConeHadronFlavourLabel (const xAOD::Jet& jet);
+  std::vector<std::string> split(const std::string& str, char token);
+  //*********************************//
+  // Prop. of BTaggingEfficiencyTool //
+  //*********************************//
+
+  /// name of the data/MC efficiency scale factor calibration file (may be changed by the @c PathResolver)
+  std::string m_SFFile;
+  /// name of the optional MC efficiency file (may be changed by the @c PathResolver)
+  std::string m_EffFile;
+  /// name of the data/MC scale factor calibration for b jets
+  std::string m_SFBName;
+  /// name of the data/MC scale factor calibration for charm jets
+  std::string m_SFCName;
+  /// name of the data/MC scale factor calibration for tau jets
+  std::string m_SFTName;
+  /// name of the data/MC scale factor calibration for light-flavour jets
+  std::string m_SFLightName;
+  /// specification of the eigenvector reduction strategy for b jets (if eigenvectors are used)
+  std::string m_EVReductionB;
+  /// specification of the eigenvector reduction strategy for c jets (if eigenvectors are used)
+  std::string m_EVReductionC;
+  /// specification of the eigenvector reduction strategy for light-flavour jets (if eigenvectors are used)
+  std::string m_EVReductionLight;
+  /// semicolon-separated list of MC efficiency parametrisation names for b jets
+  std::string m_EffBName;
+  /// semicolon-separated list of MC efficiency parametrisation names for charm jets
+  std::string m_EffCName;
+  /// semicolon-separated list of MC efficiency parametrisation names for tau jets
+  std::string m_EffTName;
+  /// semicolon-separated list of MC efficiency parametrisation names for light-flavour jets
+  std::string m_EffLightName;
+  /// semicolon-separated list of uncertainties to be excluded from the eigenvector variation procedure
+  std::string m_excludeFromEV;
+  /// tagger name
+  std::string m_taggerName;
+  /// operating point
+  std::string m_OP;
+  /// operating point when running in Continuous
+  std::string m_cutBenchmark;
+  ///  jet collection name
+  std::string m_jetAuthor;
+  /// systematics model to be used (current choices are "SFEigen" and "Envelope")
+  std::string m_systStrategy;
+  /// if true, attempt to retrieve the data/MC efficiency scale factor calibration files from the @PathResolver development area
+  bool m_useDevFile;
+  /// if true, use cone-based labelling (as opposed to ghost association)
+  bool m_coneFlavourLabel;
+  /// when using cone-based labelling (see above), if true, use the "traditional" (parton-based) labelling instead of the current default (hadron-based, exclusive)
+  bool m_oldConeFlavourLabel;
+  /// in case of continuous WP you can choose to ignore some of the eigenvectors
+  std::string m_excludeEV;
+  ///possibility to compute the direct tagging SFs map directly from the TruthTaggingTool
+  bool m_doDirectTag;
+
+  //*********************************//
+  // Prop. of BTaggingSelectionTool  //
+  //*********************************//
+
+  double m_maxEta;
+  double m_minPt;
+  double m_maxRangePt;
+  //  std::string m_CutFileName;
+
+  // properties of truth tagging
+  bool m_doOnlyUpVariations;
+  bool m_ignoreSF;
+  bool m_usePerm;
+  bool m_useQuntile;
+  bool m_continuous;
+  bool m_useSys;
+  int m_nbtag;
+
+  unsigned int m_OperatingPoint_index;
+
+  std::map<std::string, asg::AnaToolHandle<IBTaggingEfficiencyTool> > m_effTool_allOP;
+
+
+  asg::AnaToolHandle<IBTaggingEfficiencyTool> m_effTool;
+  asg::AnaToolHandle<IBTaggingSelectionTool> m_selTool; //!
+
+  StatusCode check_syst_range(unsigned int sys);
+
+  std::vector<std::vector<bool> > generatePermutations(int njets, int tags, int start=0);
+
+  double trfWeight(TRFinfo &trfinf,const std::vector<bool> &tags);
+
+  StatusCode chooseAllTagPermutation(TRFinfo &trfinf,unsigned int nbtag);
+  StatusCode chooseTagPermutation(TRFinfo &trfinf,unsigned int nbtag, bool isIncl);
+  double getPermutationRW(TRFinfo &trfinf,bool isIncl,unsigned int nbtag, int sys);
+
+
+  StatusCode chooseAllTagBins(TRFinfo &trfinf);
+  StatusCode chooseTagBins_cum(TRFinfo &trfinf,std::vector<bool> &tagconf, bool isIncl, unsigned int nbtag);
+  StatusCode generateRandomTaggerScores(std::vector< std::vector<int> > &quantiles, std::vector< std::vector<double> > &scores);
+  double getTagBinsConfProb(TRFinfo &trfinf,std::vector<int> &tagws);
+  double getTagBinsRW(TRFinfo &trfinf,bool isIncl, unsigned int nbtag);
+
+
+  bool fillVariables(const xAOD::Jet& jet, Analysis::CalibrationDataVariables& x);
+  bool fillVariables(const double jetPt, const double jetEta, const double jetTagWeight, Analysis::CalibrationDataVariables& x);
+
+
+};
+
+#endif // CPBTAGGINGTRUTHTAGGINGTOOL_H
+
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingEfficiencyTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingEfficiencyTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc478ba0f68d140238da3daecc19f838d8ec17c6
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingEfficiencyTool.h
@@ -0,0 +1,8 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+#pragma message "The IBTaggingEfficiencyTool has moved to FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h . Please update your code."
+#include <FTagAnalysisInterfaces/IBTaggingEfficiencyTool.h>
+
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingSelectionTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingSelectionTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..909e70a7ca0631bcc461360c81204087c107e6c3
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingSelectionTool.h
@@ -0,0 +1,8 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma message "The IBTaggingSelectionTool has moved to FTagAnalysisInterfaces/IBTaggingSelectionTool.h . Please update your code."
+#include <FTagAnalysisInterfaces/IBTaggingSelectionTool.h>
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingTruthTaggingTool.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingTruthTaggingTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..594b019d030c7f59b9299b6affedd032ed711b92
--- /dev/null
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/IBTaggingTruthTaggingTool.h
@@ -0,0 +1,8 @@
+// Dear emacs, this is -*- c++ -*-
+
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma message "The IBTaggingTruthTaggingTool has moved to FTagAnalysisInterfaces/IBTaggingTruthTaggingTool.h . Please update your code."
+#include <FTagAnalysisInterfaces/IBTaggingTruthTaggingTool.h>
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/selection.xml b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/selection.xml
index 071e1453f681170bfd4b8d5b17bdcf69c27ba87a..ed6cc9f04fbfc81a9e43c3d277878193d66df033 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/selection.xml
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/selection.xml
@@ -2,4 +2,6 @@
 <lcgdict>
   <class name="BTaggingEfficiencyTool" />
   <class name="BTaggingSelectionTool" />
+  <class name="BTaggingTruthTaggingTool" />
+  <class name="BTaggingEigenVectorRecompositionTool" />
 </lcgdict>
diff --git a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/xAODBTaggingEfficiencyDict.h b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/xAODBTaggingEfficiencyDict.h
index 3caca03f85580c68d5e8881336a357d1651492aa..18952ec7a5edffd4953a5b153726fddf15697bcc 100644
--- a/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/xAODBTaggingEfficiencyDict.h
+++ b/PhysicsAnalysis/JetTagging/JetTagPerformanceCalibration/xAODBTaggingEfficiency/xAODBTaggingEfficiency/xAODBTaggingEfficiencyDict.h
@@ -13,5 +13,6 @@
 
 #include "xAODBTaggingEfficiency/BTaggingEfficiencyTool.h"
 #include "xAODBTaggingEfficiency/BTaggingSelectionTool.h"
-
+#include "xAODBTaggingEfficiency/BTaggingTruthTaggingTool.h"
+#include "xAODBTaggingEfficiency/BTaggingEigenVectorRecompositionTool.h"
 #endif // XAODBTAGGINGEFFICIENCY_XAODBTAGGINGEFFICIENCYDICT_H