diff --git a/CommonTools/Utils/BuildFile.xml b/CommonTools/Utils/BuildFile.xml index c96c1c6fd7411..a72a7baec88f7 100644 --- a/CommonTools/Utils/BuildFile.xml +++ b/CommonTools/Utils/BuildFile.xml @@ -1,4 +1,5 @@ + diff --git a/CommonTools/Utils/interface/TMVAEvaluator.h b/CommonTools/Utils/interface/TMVAEvaluator.h new file mode 100644 index 0000000000000..93a922733cb2a --- /dev/null +++ b/CommonTools/Utils/interface/TMVAEvaluator.h @@ -0,0 +1,33 @@ +#ifndef CommonTools_Utils_TMVAEvaluator_h +#define CommonTools_Utils_TMVAEvaluator_h + +#include +#include +#include +#include + +#include "TMVA/Reader.h" + + +class TMVAEvaluator { + + public: + TMVAEvaluator(); + ~TMVAEvaluator(); + + void initialize(const std::string & options, const std::string & method, const std::string & weightFile, + const std::vector & variables, const std::vector & spectators); + float evaluate(const std::map & inputs); + + private: + bool mIsInitialized; + + std::string mMethod; + std::unique_ptr mReader; + + std::map mVariables; + std::map mSpectators; +}; + +#endif // CommonTools_Utils_TMVAEvaluator_h + diff --git a/CommonTools/Utils/src/TMVAEvaluator.cc b/CommonTools/Utils/src/TMVAEvaluator.cc new file mode 100644 index 0000000000000..9131ad786d0e1 --- /dev/null +++ b/CommonTools/Utils/src/TMVAEvaluator.cc @@ -0,0 +1,74 @@ +#include "CommonTools/Utils/interface/TMVAEvaluator.h" + +#include "CommonTools/Utils/interface/TMVAZipReader.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + + +TMVAEvaluator::TMVAEvaluator() : + mIsInitialized(false) +{ +} + + +TMVAEvaluator::~TMVAEvaluator() +{ +} + + +void TMVAEvaluator::initialize(const std::string & options, const std::string & method, const std::string & weightFile, + const std::vector & variables, const std::vector & spectators) +{ + // initialize the TMVA reader + mReader.reset(new TMVA::Reader(options.c_str())); + mReader->SetVerbose(false); + mMethod = method; + + // add input variables + for(std::vector::const_iterator it = variables.begin(); it!=variables.end(); ++it) + { + mVariables.insert( std::pair(*it,0.) ); + mReader->AddVariable(it->c_str(), &mVariables.at(*it)); + } + + // add spectator variables + for(std::vector::const_iterator it = spectators.begin(); it!=spectators.end(); ++it) + { + mSpectators.insert( std::pair(*it,0.) ); + mReader->AddSpectator(it->c_str(), &mSpectators.at(*it)); + } + + // load the TMVA weights + reco::details::loadTMVAWeights(mReader.get(), mMethod.c_str(), weightFile.c_str()); + + mIsInitialized = true; +} + + +float TMVAEvaluator::evaluate(const std::map & inputs) +{ + if(!mIsInitialized) + { + edm::LogError("InitializationError") << "TMVAEvaluator not properly initialized."; + return -99.; + } + + if( inputs.size() < mVariables.size() ) + { + edm::LogError("MissingInputVariable(s)") << "Too few input variables provided (" << inputs.size() << " provided but " << mVariables.size() << " expected)."; + return -99.; + } + + // set the input variable values + for(std::map::iterator it = mVariables.begin(); it!=mVariables.end(); ++it) + { + if (inputs.count(it->first)>0) + it->second = inputs.at(it->first); + else + edm::LogError("MissingInputVariable") << "Variable " << it->first << " is missing from the list of input variables. The returned discriminator value might not be sensible."; + } + + // evaluate the MVA + float value = mReader->EvaluateMVA(mMethod.c_str()); + + return value; +} diff --git a/RecoBTag/SecondaryVertex/interface/CandidateBoostedDoubleSecondaryVertexComputer.h b/RecoBTag/SecondaryVertex/interface/CandidateBoostedDoubleSecondaryVertexComputer.h index 7f26783fbc1c2..354f09f71b291 100644 --- a/RecoBTag/SecondaryVertex/interface/CandidateBoostedDoubleSecondaryVertexComputer.h +++ b/RecoBTag/SecondaryVertex/interface/CandidateBoostedDoubleSecondaryVertexComputer.h @@ -2,12 +2,12 @@ #define RecoBTag_SecondaryVertex_CandidateBoostedDoubleSecondaryVertexComputer_h #include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "CommonTools/Utils/interface/TMVAEvaluator.h" #include "RecoBTau/JetTagComputer/interface/JetTagComputer.h" #include "DataFormats/JetReco/interface/JetCollection.h" #include "DataFormats/VertexReco/interface/Vertex.h" #include "DataFormats/VertexReco/interface/VertexFwd.h" #include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h" -#include "RecoBTag/SecondaryVertex/interface/MvaBoostedDoubleSecondaryVertexEstimator.h" #include "RecoBTag/SecondaryVertex/interface/TrackKinematics.h" #include "fastjet/PseudoJet.hh" @@ -38,7 +38,7 @@ class CandidateBoostedDoubleSecondaryVertexComputer : public JetTagComputer { edm::FileInPath weightFile_; mutable std::mutex m_mutex; - [[cms::thread_guard("m_mutex")]] std::unique_ptr mvaID; + [[cms::thread_guard("m_mutex")]] std::unique_ptr mvaID; }; #endif // RecoBTag_SecondaryVertex_CandidateBoostedDoubleSecondaryVertexComputer_h diff --git a/RecoBTag/SecondaryVertex/interface/MvaBoostedDoubleSecondaryVertexEstimator.h b/RecoBTag/SecondaryVertex/interface/MvaBoostedDoubleSecondaryVertexEstimator.h deleted file mode 100644 index ff36af33fe998..0000000000000 --- a/RecoBTag/SecondaryVertex/interface/MvaBoostedDoubleSecondaryVertexEstimator.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef RecoBTag_SecondaryVertex_MvaBoostedDoubleSecondaryVertexEstimator_h -#define RecoBTag_SecondaryVertex_MvaBoostedDoubleSecondaryVertexEstimator_h - -#include "FWCore/ParameterSet/interface/ParameterSet.h" - -#include -#include "TMVA/Factory.h" -#include "TMVA/Tools.h" -#include "TMVA/Reader.h" - -class MvaBoostedDoubleSecondaryVertexEstimator { - - public: - MvaBoostedDoubleSecondaryVertexEstimator(const std::string &); - ~MvaBoostedDoubleSecondaryVertexEstimator(); - - float mvaValue(float, float, float, float, float, float, float, float, float, float); - - private: - - TMVA::Reader* TMVAReader; - - float mva_PFLepton_ptrel, mva_z_ratio, mva_tau_dot, mva_SV_mass_0, mva_SV_EnergyRatio_0, - mva_SV_EnergyRatio_1, mva_PFLepton_IP2D, mva_tau21, mva_nSL, mva_jetNTracksEtaRel; - float mva_massGroomed, mva_flavour, mva_nbHadrons, mva_ptGroomed, mva_etaGroomed; -}; - -#endif // RecoBTag_SecondaryVertex_MvaBoostedDoubleSecondaryVertexEstimator_h - diff --git a/RecoBTag/SecondaryVertex/src/CandidateBoostedDoubleSecondaryVertexComputer.cc b/RecoBTag/SecondaryVertex/src/CandidateBoostedDoubleSecondaryVertexComputer.cc index c2bb9908e8d27..cfd4bda0f9932 100644 --- a/RecoBTag/SecondaryVertex/src/CandidateBoostedDoubleSecondaryVertexComputer.cc +++ b/RecoBTag/SecondaryVertex/src/CandidateBoostedDoubleSecondaryVertexComputer.cc @@ -20,7 +20,14 @@ CandidateBoostedDoubleSecondaryVertexComputer::CandidateBoostedDoubleSecondaryVe uses(2, "muonTagInfos"); uses(3, "elecTagInfos"); - mvaID.reset(new MvaBoostedDoubleSecondaryVertexEstimator(weightFile_.fullPath())); + mvaID.reset(new TMVAEvaluator()); + + // variable order needs to be the same as in the training + std::vector variables({"PFLepton_ptrel", "z_ratio1", "tau_dot", "SV_mass_0", "SV_vtx_EnergyRatio_0", + "SV_vtx_EnergyRatio_1","PFLepton_IP2D", "tau2/tau1", "nSL", "jetNTracksEtaRel"}); + std::vector spectators({"massGroomed", "flavour", "nbHadrons", "ptGroomed", "etaGroomed"}); + + mvaID->initialize("Color:Silent:Error", "BDTG", weightFile_.fullPath(), variables, spectators); } @@ -35,7 +42,7 @@ float CandidateBoostedDoubleSecondaryVertexComputer::discriminator(const TagInfo // default discriminator value float value = -10.; - // MvaBoostedDoubleSecondaryVertexEstimator is not thread safe + // TMVAEvaluator is not thread safe std::lock_guard lock(m_mutex); // default variable values @@ -143,8 +150,20 @@ float CandidateBoostedDoubleSecondaryVertexComputer::discriminator(const TagInfo } } + std::map inputs; + inputs["z_ratio1"] = z_ratio; + inputs["tau_dot"] = tau_dot; + inputs["SV_mass_0"] = SV_mass_0; + inputs["SV_vtx_EnergyRatio_0"] = SV_EnergyRatio_0; + inputs["SV_vtx_EnergyRatio_1"] = SV_EnergyRatio_1; + inputs["jetNTracksEtaRel"] = vertexNTracks; + inputs["PFLepton_ptrel"] = PFLepton_ptrel; + inputs["PFLepton_IP2D"] = PFLepton_IP2D; + inputs["nSL"] = nSL; + inputs["tau2/tau1"] = tau21; + // evaluate the MVA - value = mvaID->mvaValue(PFLepton_ptrel, z_ratio, tau_dot, SV_mass_0, SV_EnergyRatio_0, SV_EnergyRatio_1, PFLepton_IP2D, tau21, nSL, vertexNTracks); + value = mvaID->evaluate(inputs); // return the final discriminator value return value; diff --git a/RecoBTag/SecondaryVertex/src/MvaBoostedDoubleSecondaryVertexEstimator.cc b/RecoBTag/SecondaryVertex/src/MvaBoostedDoubleSecondaryVertexEstimator.cc deleted file mode 100644 index a0ece9d68189b..0000000000000 --- a/RecoBTag/SecondaryVertex/src/MvaBoostedDoubleSecondaryVertexEstimator.cc +++ /dev/null @@ -1,57 +0,0 @@ -#include "RecoBTag/SecondaryVertex/interface/MvaBoostedDoubleSecondaryVertexEstimator.h" - -#include "CommonTools/Utils/interface/TMVAZipReader.h" - - -MvaBoostedDoubleSecondaryVertexEstimator::MvaBoostedDoubleSecondaryVertexEstimator(const std::string & weightFile) -{ - TMVAReader = new TMVA::Reader("Color:Silent:Error"); - TMVAReader->SetVerbose(false); - - TMVAReader->AddVariable("PFLepton_ptrel", &mva_PFLepton_ptrel); - TMVAReader->AddVariable("z_ratio1", &mva_z_ratio); - TMVAReader->AddVariable("tau_dot", &mva_tau_dot); - TMVAReader->AddVariable("SV_mass_0", &mva_SV_mass_0); - TMVAReader->AddVariable("SV_vtx_EnergyRatio_0", &mva_SV_EnergyRatio_0); - TMVAReader->AddVariable("SV_vtx_EnergyRatio_1", &mva_SV_EnergyRatio_1); - TMVAReader->AddVariable("PFLepton_IP2D", &mva_PFLepton_IP2D); - TMVAReader->AddVariable("tau2/tau1", &mva_tau21); - TMVAReader->AddVariable("nSL", &mva_nSL); - TMVAReader->AddVariable("jetNTracksEtaRel", &mva_jetNTracksEtaRel); - - TMVAReader->AddSpectator("massGroomed", &mva_massGroomed); - TMVAReader->AddSpectator("flavour", &mva_flavour); - TMVAReader->AddSpectator("nbHadrons", &mva_nbHadrons); - TMVAReader->AddSpectator("ptGroomed", &mva_ptGroomed); - TMVAReader->AddSpectator("etaGroomed", &mva_etaGroomed); - - reco::details::loadTMVAWeights(TMVAReader, "BDTG", weightFile.c_str()); -} - - -MvaBoostedDoubleSecondaryVertexEstimator::~MvaBoostedDoubleSecondaryVertexEstimator() -{ - delete TMVAReader; -} - - -float MvaBoostedDoubleSecondaryVertexEstimator::mvaValue(float PFLepton_ptrel, float z_ratio, float tau_dot, float SV_mass_0, - float SV_EnergyRatio_0, float SV_EnergyRatio_1, float PFLepton_IP2D, - float tau21, float nSL, float jetNTracksEtaRel) -{ - mva_PFLepton_ptrel = PFLepton_ptrel; - mva_z_ratio = z_ratio; - mva_tau_dot = tau_dot; - mva_SV_mass_0 = SV_mass_0; - mva_SV_EnergyRatio_0 = SV_EnergyRatio_0; - mva_SV_EnergyRatio_1 = SV_EnergyRatio_1; - mva_PFLepton_IP2D = PFLepton_IP2D; - mva_tau21 = tau21; - mva_nSL = nSL; - mva_jetNTracksEtaRel = jetNTracksEtaRel; - - // evaluate the MVA - float value = TMVAReader->EvaluateMVA("BDTG"); - - return value; -}