diff --git a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py index 89a9277aaeb9b..8e6d3e39e9329 100644 --- a/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py +++ b/PhysicsTools/PatAlgos/python/recoLayer0/bTagging_cff.py @@ -193,6 +193,10 @@ , 'pfDeepFlavourJetTags:probuds' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] , 'pfDeepFlavourJetTags:probg' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] , 'pfDeepVertexJetTags:probb' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] + , 'pfDeepCombinedJetTags:probb' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] + , 'pfDeepCombinedJetTags:probc' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] + , 'pfDeepCombinedJetTags:probuds' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] + , 'pfDeepCombinedJetTags:probg' : [["pfDeepFlavourTagInfos"], ['pfDeepCSVTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderTagInfos']] , 'pfNegativeDeepFlavourJetTags:probb' : [["pfNegativeDeepFlavourTagInfos"], ['pfDeepCSVNegativeTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderNegativeTagInfos']] , 'pfNegativeDeepFlavourJetTags:probbb' : [["pfNegativeDeepFlavourTagInfos"], ['pfDeepCSVNegativeTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderNegativeTagInfos']] , 'pfNegativeDeepFlavourJetTags:problepb' : [["pfNegativeDeepFlavourTagInfos"], ['pfDeepCSVNegativeTagInfos', "pfImpactParameterTagInfos", 'pfInclusiveSecondaryVertexFinderNegativeTagInfos']] diff --git a/RecoBTag/TensorFlow/BuildFile.xml b/RecoBTag/ONNXRuntime/BuildFile.xml similarity index 63% rename from RecoBTag/TensorFlow/BuildFile.xml rename to RecoBTag/ONNXRuntime/BuildFile.xml index 12e3ac6997187..f75e71b863efd 100644 --- a/RecoBTag/TensorFlow/BuildFile.xml +++ b/RecoBTag/ONNXRuntime/BuildFile.xml @@ -1,5 +1,6 @@ - + + diff --git a/RecoBTag/ONNXRuntime/interface/tensor_configs.h b/RecoBTag/ONNXRuntime/interface/tensor_configs.h new file mode 100644 index 0000000000000..e528b4e92f74a --- /dev/null +++ b/RecoBTag/ONNXRuntime/interface/tensor_configs.h @@ -0,0 +1,31 @@ +#ifndef RecoBTag_ONNXRuntime_tensor_configs_h +#define RecoBTag_ONNXRuntime_tensor_configs_h + +namespace deepflavour { + + constexpr unsigned n_features_global = 15; + + constexpr unsigned n_cpf = 25; + constexpr unsigned n_features_cpf = 16; + + constexpr unsigned n_npf = 25; + constexpr unsigned n_features_npf = 6; + + constexpr unsigned n_sv = 4; + constexpr unsigned n_features_sv = 12; + +} // namespace deepflavour + +namespace deepvertex { + + constexpr unsigned n_features_global = 4; + + constexpr unsigned n_seed = 10; + constexpr unsigned n_features_seed = 21; + + constexpr unsigned n_neighbor = 20; + constexpr unsigned n_features_neighbor = 36; + +} // namespace deepvertex + +#endif diff --git a/RecoBTag/ONNXRuntime/interface/tensor_fillers.h b/RecoBTag/ONNXRuntime/interface/tensor_fillers.h new file mode 100644 index 0000000000000..bb1a25a2d0f0b --- /dev/null +++ b/RecoBTag/ONNXRuntime/interface/tensor_fillers.h @@ -0,0 +1,24 @@ +#ifndef RecoBTag_ONNXRuntime_tensor_fillers_h +#define RecoBTag_ONNXRuntime_tensor_fillers_h + +#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h" + +namespace btagbtvdeep { + + void jet_tensor_filler(float*& ptr, const btagbtvdeep::DeepFlavourFeatures& features); + + void cpf_tensor_filler(float*& ptr, const btagbtvdeep::ChargedCandidateFeatures& c_pf_features); + + void npf_tensor_filler(float*& ptr, const btagbtvdeep::NeutralCandidateFeatures& n_pf_features); + + void sv_tensor_filler(float*& ptr, const btagbtvdeep::SecondaryVertexFeatures& sv_features); + + void jet4vec_tensor_filler(float*& ptr, const btagbtvdeep::JetFeatures& jet_features); + + void seedTrack_tensor_filler(float*& ptr, const btagbtvdeep::SeedingTrackFeatures& seed_features); + + void neighbourTrack_tensor_filler(float*& ptr, const btagbtvdeep::TrackPairFeatures& neighbourTrack_features); + +} // namespace btagbtvdeep + +#endif diff --git a/RecoBTag/ONNXRuntime/plugins/BuildFile.xml b/RecoBTag/ONNXRuntime/plugins/BuildFile.xml index 286d9847a92b3..251a68aa90c81 100644 --- a/RecoBTag/ONNXRuntime/plugins/BuildFile.xml +++ b/RecoBTag/ONNXRuntime/plugins/BuildFile.xml @@ -4,5 +4,6 @@ + diff --git a/RecoBTag/ONNXRuntime/plugins/DeepCombinedONNXJetTagsProducer.cc b/RecoBTag/ONNXRuntime/plugins/DeepCombinedONNXJetTagsProducer.cc new file mode 100644 index 0000000000000..99193460081a7 --- /dev/null +++ b/RecoBTag/ONNXRuntime/plugins/DeepCombinedONNXJetTagsProducer.cc @@ -0,0 +1,300 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/Framework/interface/makeRefToBaseProdFrom.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/BTauReco/interface/JetTag.h" + +#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h" + +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" + +#include "RecoBTag/ONNXRuntime/interface/tensor_fillers.h" +#include "RecoBTag/ONNXRuntime/interface/tensor_configs.h" + +using namespace cms::Ort; + +class DeepCombinedONNXJetTagsProducer : public edm::stream::EDProducer> { +public: + explicit DeepCombinedONNXJetTagsProducer(const edm::ParameterSet&, const ONNXRuntime*); + ~DeepCombinedONNXJetTagsProducer() override; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + + static std::unique_ptr initializeGlobalCache(const edm::ParameterSet&); + static void globalEndJob(const ONNXRuntime*); + +private: + typedef std::vector TagInfoCollection; + typedef reco::JetTagCollection JetTagCollection; + + void produce(edm::Event&, const edm::EventSetup&) override; + + void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo); + + const edm::EDGetTokenT src_; + std::vector flav_names_; + std::vector input_names_; + std::vector output_names_; + + const double min_jet_pt_; + const double max_jet_eta_; + + enum InputIndexes { + kGlobal = 0, + kChargedCandidates = 1, + kNeutralCandidates = 2, + kVertices = 3, + kGlobal1 = 4, + kSeedingTracks = 5, + kNeighbourTracks = 6 + }; + const static unsigned n_features_global_ = deepflavour::n_features_global; + const static unsigned n_cpf_ = deepflavour::n_cpf; + const static unsigned n_features_cpf_ = deepflavour::n_features_cpf; + const static unsigned n_npf_ = deepflavour::n_npf; + const static unsigned n_features_npf_ = deepflavour::n_features_npf; + const static unsigned n_sv_ = deepflavour::n_sv; + const static unsigned n_features_sv_ = deepflavour::n_features_sv; + const static unsigned n_features_global1_ = deepvertex::n_features_global; + const static unsigned n_seed_ = deepvertex::n_seed; + const static unsigned n_features_seed_ = deepvertex::n_features_seed; + const static unsigned n_neighbor_ = deepvertex::n_neighbor; + const static unsigned n_features_neighbor_ = deepvertex::n_features_neighbor; + + const static std::vector input_sizes_; + + // hold the input data + FloatArrays data_; +}; + +const std::vector DeepCombinedONNXJetTagsProducer::input_sizes_{n_features_global_, + n_cpf_* n_features_cpf_, + n_npf_* n_features_npf_, + n_sv_* n_features_sv_, + n_features_global1_, + n_seed_* n_features_seed_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_}; + +DeepCombinedONNXJetTagsProducer::DeepCombinedONNXJetTagsProducer(const edm::ParameterSet& iConfig, + const ONNXRuntime* cache) + : src_(consumes(iConfig.getParameter("src"))), + flav_names_(iConfig.getParameter>("flav_names")), + input_names_(iConfig.getParameter>("input_names")), + output_names_(iConfig.getParameter>("output_names")), + min_jet_pt_(iConfig.getParameter("min_jet_pt")), + max_jet_eta_(iConfig.getParameter("max_jet_eta")) { + // get output names from flav_names + for (const auto& flav_name : flav_names_) { + produces(flav_name); + } + + assert(input_names_.size() == input_sizes_.size()); +} + +DeepCombinedONNXJetTagsProducer::~DeepCombinedONNXJetTagsProducer() {} + +void DeepCombinedONNXJetTagsProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // pfDeepFlavourJetTags + edm::ParameterSetDescription desc; + desc.add("src", edm::InputTag("pfDeepFlavourTagInfos")); + desc.add>("input_names", + {"input_1_DFla", + "input_2_DFla", + "input_3_DFla", + "input_4_DFla", + "input_1", + "input_2", + "input_3", + "input_4", + "input_5", + "input_6", + "input_7", + "input_8", + "input_9", + "input_10", + "input_11", + "input_12"}); + desc.add("model_path", + edm::FileInPath("RecoBTag/Combined/data/DeepVertex/phase1_deepvertexcombined.onnx")); + desc.add>("output_names", {"dense_13"}); + desc.add>("flav_names", std::vector{"probb", "probc", "probuds", "probg"}); + desc.add("min_jet_pt", 15.0); + desc.add("max_jet_eta", 2.5); + + descriptions.add("pfDeepCombinedJetTags", desc); +} + +std::unique_ptr DeepCombinedONNXJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) { + return std::make_unique(iConfig.getParameter("model_path").fullPath()); +} + +void DeepCombinedONNXJetTagsProducer::globalEndJob(const ONNXRuntime* cache) {} + +void DeepCombinedONNXJetTagsProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + edm::Handle tag_infos; + iEvent.getByToken(src_, tag_infos); + + data_.clear(); + + std::vector> output_tags; + if (!tag_infos->empty()) { + unsigned good_taginfo_count = 0; + std::vector good_taginfo_jets(tag_infos->size(), false); + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + const auto& jet_ref = (*tag_infos)[jet_n].jet(); + if (jet_ref->pt() > min_jet_pt_ && std::fabs(jet_ref->eta()) < max_jet_eta_) { + good_taginfo_count++; + good_taginfo_jets[jet_n] = true; + } + } + + // init data storage w correct size + for (const auto& len : input_sizes_) { + data_.emplace_back(good_taginfo_count * len, 0); + } + + // initialize output collection + auto jet_ref = tag_infos->begin()->jet(); + auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent); + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique(ref2prod)); + } + + // convert inputs + unsigned inputs_done_count = 0; + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + if (good_taginfo_jets[jet_n]) { + const auto& taginfo = (*tag_infos)[jet_n]; + make_inputs(inputs_done_count, taginfo); + inputs_done_count++; + } + } + + // run prediction + assert(inputs_done_count == good_taginfo_count); + const auto outputs = globalCache()->run(input_names_, data_, {}, output_names_, good_taginfo_count)[0]; + assert(outputs.size() == flav_names_.size() * good_taginfo_count); + + // get the outputs + unsigned i_output = 0; + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + const auto& jet_ref = (*tag_infos)[jet_n].jet(); + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) { + if (good_taginfo_jets[jet_n]) { + (*(output_tags[flav_n]))[jet_ref] = outputs[i_output]; + ++i_output; + } else { + (*(output_tags[flav_n]))[jet_ref] = -2; + } + } + } + } else { + // create empty output collection + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique()); + } + } + + // put into the event + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) { + iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]); + } +} + +void DeepCombinedONNXJetTagsProducer::make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo) { + const auto& features = taginfo.features(); + float* ptr = nullptr; + const float* start = nullptr; + unsigned offset = 0; + + // jet and other global features + offset = i_jet * input_sizes_[kGlobal]; + ptr = &data_[kGlobal][offset]; + start = ptr; + jet_tensor_filler(ptr, features); + assert(start + n_features_global_ - 1 == ptr); + + // c_pf candidates + auto max_c_pf_n = std::min(features.c_pf_features.size(), (std::size_t)n_cpf_); + offset = i_jet * input_sizes_[kChargedCandidates]; + for (std::size_t c_pf_n = 0; c_pf_n < max_c_pf_n; c_pf_n++) { + const auto& c_pf_features = features.c_pf_features[c_pf_n]; + ptr = &data_[kChargedCandidates][offset + c_pf_n * n_features_cpf_]; + start = ptr; + cpf_tensor_filler(ptr, c_pf_features); + assert(start + n_features_cpf_ - 1 == ptr); + } + + // n_pf candidates + auto max_n_pf_n = std::min(features.n_pf_features.size(), (std::size_t)n_npf_); + offset = i_jet * input_sizes_[kNeutralCandidates]; + for (std::size_t n_pf_n = 0; n_pf_n < max_n_pf_n; n_pf_n++) { + const auto& n_pf_features = features.n_pf_features[n_pf_n]; + ptr = &data_[kNeutralCandidates][offset + n_pf_n * n_features_npf_]; + start = ptr; + npf_tensor_filler(ptr, n_pf_features); + assert(start + n_features_npf_ - 1 == ptr); + } + + // sv candidates + auto max_sv_n = std::min(features.sv_features.size(), (std::size_t)n_sv_); + offset = i_jet * input_sizes_[kVertices]; + for (std::size_t sv_n = 0; sv_n < max_sv_n; sv_n++) { + const auto& sv_features = features.sv_features[sv_n]; + ptr = &data_[kVertices][offset + sv_n * n_features_sv_]; + start = ptr; + sv_tensor_filler(ptr, sv_features); + assert(start + n_features_sv_ - 1 == ptr); + } + + // jet variables + offset = i_jet * input_sizes_[kGlobal1]; + const auto& jet_features = features.jet_features; + ptr = &data_[kGlobal1][offset]; + start = ptr; + jet4vec_tensor_filler(ptr, jet_features); + assert(start + n_features_global1_ - 1 == ptr); + + // seeds + auto max_seed_n = std::min(features.seed_features.size(), (std::size_t)n_seed_); + offset = i_jet * input_sizes_[kSeedingTracks]; + for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) { + const auto& seed_features = features.seed_features[seed_n]; + ptr = &data_[kSeedingTracks][offset + seed_n * n_features_seed_]; + start = ptr; + seedTrack_tensor_filler(ptr, seed_features); + assert(start + n_features_seed_ - 1 == ptr); + } + + // neighbours + offset = i_jet * input_sizes_[kNeighbourTracks]; + for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) { + const auto& neighbourTracks_features = features.seed_features[seed_n].nearTracks; + auto max_neighbour_n = std::min(neighbourTracks_features.size(), (std::size_t)n_neighbor_); + for (std::size_t neighbour_n = 0; neighbour_n < max_neighbour_n; neighbour_n++) { + ptr = &data_[kNeighbourTracks + seed_n][offset + neighbour_n * n_features_neighbor_]; + start = ptr; + neighbourTrack_tensor_filler(ptr, neighbourTracks_features[neighbour_n]); + assert(start + n_features_neighbor_ - 1 == ptr); + } + } +} + +//define this as a plug-in +DEFINE_FWK_MODULE(DeepCombinedONNXJetTagsProducer); diff --git a/RecoBTag/ONNXRuntime/plugins/DeepVertexONNXJetTagsProducer.cc b/RecoBTag/ONNXRuntime/plugins/DeepVertexONNXJetTagsProducer.cc new file mode 100644 index 0000000000000..c9805e66f04f7 --- /dev/null +++ b/RecoBTag/ONNXRuntime/plugins/DeepVertexONNXJetTagsProducer.cc @@ -0,0 +1,235 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/Framework/interface/makeRefToBaseProdFrom.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/BTauReco/interface/JetTag.h" + +#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h" + +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" + +#include "RecoBTag/ONNXRuntime/interface/tensor_fillers.h" +#include "RecoBTag/ONNXRuntime/interface/tensor_configs.h" + +using namespace cms::Ort; + +class DeepVertexONNXJetTagsProducer : public edm::stream::EDProducer> { +public: + explicit DeepVertexONNXJetTagsProducer(const edm::ParameterSet&, const ONNXRuntime*); + ~DeepVertexONNXJetTagsProducer() override; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + + static std::unique_ptr initializeGlobalCache(const edm::ParameterSet&); + static void globalEndJob(const ONNXRuntime*); + +private: + typedef std::vector TagInfoCollection; + typedef reco::JetTagCollection JetTagCollection; + + void produce(edm::Event&, const edm::EventSetup&) override; + + void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo); + + const edm::EDGetTokenT src_; + std::vector flav_names_; + std::vector input_names_; + std::vector output_names_; + + const double min_jet_pt_; + const double max_jet_eta_; + + enum InputIndexes { kGlobal = 0, kSeedingTracks = 1, kNeighbourTracks = 2 }; + const static unsigned n_features_global_ = deepvertex::n_features_global; + const static unsigned n_seed_ = deepvertex::n_seed; + const static unsigned n_features_seed_ = deepvertex::n_features_seed; + const static unsigned n_neighbor_ = deepvertex::n_neighbor; + const static unsigned n_features_neighbor_ = deepvertex::n_features_neighbor; + + const static std::vector input_sizes_; + + // hold the input data + FloatArrays data_; +}; + +const std::vector DeepVertexONNXJetTagsProducer::input_sizes_{n_features_global_, + n_seed_* n_features_seed_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_, + n_neighbor_* n_features_neighbor_}; + +DeepVertexONNXJetTagsProducer::DeepVertexONNXJetTagsProducer(const edm::ParameterSet& iConfig, const ONNXRuntime* cache) + : src_(consumes(iConfig.getParameter("src"))), + flav_names_(iConfig.getParameter>("flav_names")), + input_names_(iConfig.getParameter>("input_names")), + output_names_(iConfig.getParameter>("output_names")), + min_jet_pt_(iConfig.getParameter("min_jet_pt")), + max_jet_eta_(iConfig.getParameter("max_jet_eta")) { + // get output names from flav_names + for (const auto& flav_name : flav_names_) { + produces(flav_name); + } + + assert(input_names_.size() == input_sizes_.size()); +} + +DeepVertexONNXJetTagsProducer::~DeepVertexONNXJetTagsProducer() {} + +void DeepVertexONNXJetTagsProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // pfDeepFlavourJetTags + edm::ParameterSetDescription desc; + desc.add("src", edm::InputTag("pfDeepFlavourTagInfos")); + desc.add>("input_names", + {"input_1", + "input_2", + "input_3", + "input_4", + "input_5", + "input_6", + "input_7", + "input_8", + "input_9", + "input_10", + "input_11", + "input_12"}); + desc.add("model_path", edm::FileInPath("RecoBTag/Combined/data/DeepVertex/phase1_deepvertex.onnx")); + desc.add>("output_names", {"dense_6"}); + desc.add>("flav_names", std::vector{"probb", "probc", "probuds", "probg"}); + desc.add("min_jet_pt", 15.0); + desc.add("max_jet_eta", 2.5); + + descriptions.add("pfDeepVertexJetTags", desc); +} + +std::unique_ptr DeepVertexONNXJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) { + return std::make_unique(iConfig.getParameter("model_path").fullPath()); +} + +void DeepVertexONNXJetTagsProducer::globalEndJob(const ONNXRuntime* cache) {} + +void DeepVertexONNXJetTagsProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + edm::Handle tag_infos; + iEvent.getByToken(src_, tag_infos); + + data_.clear(); + + std::vector> output_tags; + if (!tag_infos->empty()) { + unsigned good_taginfo_count = 0; + std::vector good_taginfo_jets(tag_infos->size(), false); + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + const auto& jet_ref = (*tag_infos)[jet_n].jet(); + if (jet_ref->pt() > min_jet_pt_ && std::fabs(jet_ref->eta()) < max_jet_eta_) { + good_taginfo_count++; + good_taginfo_jets[jet_n] = true; + } + } + + // init data storage w correct size + for (const auto& len : input_sizes_) { + data_.emplace_back(good_taginfo_count * len, 0); + } + + // initialize output collection + auto jet_ref = tag_infos->begin()->jet(); + auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent); + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique(ref2prod)); + } + + // convert inputs + unsigned inputs_done_count = 0; + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + if (good_taginfo_jets[jet_n]) { + const auto& taginfo = (*tag_infos)[jet_n]; + make_inputs(inputs_done_count, taginfo); + inputs_done_count++; + } + } + + // run prediction + assert(inputs_done_count == good_taginfo_count); + const auto outputs = globalCache()->run(input_names_, data_, {}, output_names_, good_taginfo_count)[0]; + assert(outputs.size() == flav_names_.size() * good_taginfo_count); + + // get the outputs + unsigned i_output = 0; + for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) { + const auto& jet_ref = (*tag_infos)[jet_n].jet(); + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) { + if (good_taginfo_jets[jet_n]) { + (*(output_tags[flav_n]))[jet_ref] = outputs[i_output]; + ++i_output; + } else { + (*(output_tags[flav_n]))[jet_ref] = -2; + } + } + } + } else { + // create empty output collection + for (std::size_t i = 0; i < flav_names_.size(); i++) { + output_tags.emplace_back(std::make_unique()); + } + } + + // put into the event + for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) { + iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]); + } +} + +void DeepVertexONNXJetTagsProducer::make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo) { + const auto& features = taginfo.features(); + float* ptr = nullptr; + const float* start = nullptr; + unsigned offset = 0; + + // jet variables + offset = i_jet * input_sizes_[kGlobal]; + const auto& jet_features = features.jet_features; + ptr = &data_[kGlobal][offset]; + start = ptr; + jet4vec_tensor_filler(ptr, jet_features); + assert(start + n_features_global_ - 1 == ptr); + + // seeds + auto max_seed_n = std::min(features.seed_features.size(), (std::size_t)n_seed_); + offset = i_jet * input_sizes_[kSeedingTracks]; + for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) { + const auto& seed_features = features.seed_features[seed_n]; + ptr = &data_[kSeedingTracks][offset + seed_n * n_features_seed_]; + start = ptr; + seedTrack_tensor_filler(ptr, seed_features); + assert(start + n_features_seed_ - 1 == ptr); + } + + // neighbours + offset = i_jet * input_sizes_[kNeighbourTracks]; + for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) { + const auto& neighbourTracks_features = features.seed_features[seed_n].nearTracks; + auto max_neighbour_n = std::min(neighbourTracks_features.size(), (std::size_t)n_neighbor_); + for (std::size_t neighbour_n = 0; neighbour_n < max_neighbour_n; neighbour_n++) { + ptr = &data_[kNeighbourTracks + seed_n][offset + neighbour_n * n_features_neighbor_]; + start = ptr; + neighbourTrack_tensor_filler(ptr, neighbourTracks_features[neighbour_n]); + assert(start + n_features_neighbor_ - 1 == ptr); + } + } +} + +//define this as a plug-in +DEFINE_FWK_MODULE(DeepVertexONNXJetTagsProducer); diff --git a/RecoBTag/ONNXRuntime/python/pfDeepFlavour_cff.py b/RecoBTag/ONNXRuntime/python/pfDeepFlavour_cff.py index a68d2585bad19..e4c446a178028 100644 --- a/RecoBTag/ONNXRuntime/python/pfDeepFlavour_cff.py +++ b/RecoBTag/ONNXRuntime/python/pfDeepFlavour_cff.py @@ -5,7 +5,8 @@ from RecoBTag.FeatureTools.pfDeepDoubleXTagInfos_cfi import pfDeepDoubleXTagInfos from RecoBTag.ONNXRuntime.pfDeepFlavourJetTags_cfi import pfDeepFlavourJetTags -from RecoBTag.TensorFlow.pfDeepVertexJetTags_cfi import pfDeepVertexJetTags +from RecoBTag.ONNXRuntime.pfDeepVertexJetTags_cfi import pfDeepVertexJetTags +from RecoBTag.ONNXRuntime.pfDeepCombinedJetTags_cfi import pfDeepCombinedJetTags from RecoBTag.ONNXRuntime.pfNegativeDeepFlavourJetTags_cfi import pfNegativeDeepFlavourJetTags from CommonTools.PileupAlgos.Puppi_cff import puppi from PhysicsTools.PatAlgos.slimming.primaryVertexAssociation_cfi import primaryVertexAssociation diff --git a/RecoBTag/ONNXRuntime/src/tensor_fillers.cc b/RecoBTag/ONNXRuntime/src/tensor_fillers.cc new file mode 100644 index 0000000000000..da49b1b0119d7 --- /dev/null +++ b/RecoBTag/ONNXRuntime/src/tensor_fillers.cc @@ -0,0 +1,141 @@ +#include "RecoBTag/ONNXRuntime/interface/tensor_fillers.h" + +namespace btagbtvdeep { + + void jet_tensor_filler(float*& ptr, const btagbtvdeep::DeepFlavourFeatures& features) { + // jet variables + const auto& jet_features = features.jet_features; + *ptr = jet_features.pt; + *(++ptr) = jet_features.eta; + // number of elements in different collections + *(++ptr) = features.c_pf_features.size(); + *(++ptr) = features.n_pf_features.size(); + *(++ptr) = features.sv_features.size(); + *(++ptr) = features.npv; + // variables from ShallowTagInfo + const auto& tag_info_features = features.tag_info_features; + *(++ptr) = tag_info_features.trackSumJetEtRatio; + *(++ptr) = tag_info_features.trackSumJetDeltaR; + *(++ptr) = tag_info_features.vertexCategory; + *(++ptr) = tag_info_features.trackSip2dValAboveCharm; + *(++ptr) = tag_info_features.trackSip2dSigAboveCharm; + *(++ptr) = tag_info_features.trackSip3dValAboveCharm; + *(++ptr) = tag_info_features.trackSip3dSigAboveCharm; + *(++ptr) = tag_info_features.jetNSelectedTracks; + *(++ptr) = tag_info_features.jetNTracksEtaRel; + } + + void cpf_tensor_filler(float*& ptr, const btagbtvdeep::ChargedCandidateFeatures& c_pf_features) { + *ptr = c_pf_features.btagPf_trackEtaRel; + *(++ptr) = c_pf_features.btagPf_trackPtRel; + *(++ptr) = c_pf_features.btagPf_trackPPar; + *(++ptr) = c_pf_features.btagPf_trackDeltaR; + *(++ptr) = c_pf_features.btagPf_trackPParRatio; + *(++ptr) = c_pf_features.btagPf_trackSip2dVal; + *(++ptr) = c_pf_features.btagPf_trackSip2dSig; + *(++ptr) = c_pf_features.btagPf_trackSip3dVal; + *(++ptr) = c_pf_features.btagPf_trackSip3dSig; + *(++ptr) = c_pf_features.btagPf_trackJetDistVal; + *(++ptr) = c_pf_features.ptrel; + *(++ptr) = c_pf_features.drminsv; + *(++ptr) = c_pf_features.vtx_ass; + *(++ptr) = c_pf_features.puppiw; + *(++ptr) = c_pf_features.chi2; + *(++ptr) = c_pf_features.quality; + } + + void npf_tensor_filler(float*& ptr, const btagbtvdeep::NeutralCandidateFeatures& n_pf_features) { + *ptr = n_pf_features.ptrel; + *(++ptr) = n_pf_features.deltaR; + *(++ptr) = n_pf_features.isGamma; + *(++ptr) = n_pf_features.hadFrac; + *(++ptr) = n_pf_features.drminsv; + *(++ptr) = n_pf_features.puppiw; + } + + void sv_tensor_filler(float*& ptr, const btagbtvdeep::SecondaryVertexFeatures& sv_features) { + *ptr = sv_features.pt; + *(++ptr) = sv_features.deltaR; + *(++ptr) = sv_features.mass; + *(++ptr) = sv_features.ntracks; + *(++ptr) = sv_features.chi2; + *(++ptr) = sv_features.normchi2; + *(++ptr) = sv_features.dxy; + *(++ptr) = sv_features.dxysig; + *(++ptr) = sv_features.d3d; + *(++ptr) = sv_features.d3dsig; + *(++ptr) = sv_features.costhetasvpv; + *(++ptr) = sv_features.enratio; + } + + void jet4vec_tensor_filler(float*& ptr, const btagbtvdeep::JetFeatures& jet_features) { + *ptr = jet_features.pt; + *(++ptr) = jet_features.eta; + *(++ptr) = jet_features.phi; + *(++ptr) = jet_features.mass; + } + + void seedTrack_tensor_filler(float*& ptr, const btagbtvdeep::SeedingTrackFeatures& seed_features) { + *ptr = seed_features.pt; + *(++ptr) = seed_features.eta; + *(++ptr) = seed_features.phi; + *(++ptr) = seed_features.mass; + *(++ptr) = seed_features.dz; + *(++ptr) = seed_features.dxy; + *(++ptr) = seed_features.ip3D; + *(++ptr) = seed_features.sip3D; + *(++ptr) = seed_features.ip2D; + *(++ptr) = seed_features.sip2D; + *(++ptr) = seed_features.signedIp3D; + *(++ptr) = seed_features.signedSip3D; + *(++ptr) = seed_features.signedIp2D; + *(++ptr) = seed_features.signedSip2D; + *(++ptr) = seed_features.trackProbability3D; + *(++ptr) = seed_features.trackProbability2D; + *(++ptr) = seed_features.chi2reduced; + *(++ptr) = seed_features.nPixelHits; + *(++ptr) = seed_features.nHits; + *(++ptr) = seed_features.jetAxisDistance; + *(++ptr) = seed_features.jetAxisDlength; + } + + void neighbourTrack_tensor_filler(float*& ptr, const btagbtvdeep::TrackPairFeatures& neighbourTrack_features) { + *ptr = neighbourTrack_features.pt; + *(++ptr) = neighbourTrack_features.eta; + *(++ptr) = neighbourTrack_features.phi; + *(++ptr) = neighbourTrack_features.dz; + *(++ptr) = neighbourTrack_features.dxy; + *(++ptr) = neighbourTrack_features.mass; + *(++ptr) = neighbourTrack_features.ip3D; + *(++ptr) = neighbourTrack_features.sip3D; + *(++ptr) = neighbourTrack_features.ip2D; + *(++ptr) = neighbourTrack_features.sip2D; + *(++ptr) = neighbourTrack_features.distPCA; + *(++ptr) = neighbourTrack_features.dsigPCA; + *(++ptr) = neighbourTrack_features.x_PCAonSeed; + *(++ptr) = neighbourTrack_features.y_PCAonSeed; + *(++ptr) = neighbourTrack_features.z_PCAonSeed; + *(++ptr) = neighbourTrack_features.xerr_PCAonSeed; + *(++ptr) = neighbourTrack_features.yerr_PCAonSeed; + *(++ptr) = neighbourTrack_features.zerr_PCAonSeed; + *(++ptr) = neighbourTrack_features.x_PCAonTrack; + *(++ptr) = neighbourTrack_features.y_PCAonTrack; + *(++ptr) = neighbourTrack_features.z_PCAonTrack; + *(++ptr) = neighbourTrack_features.xerr_PCAonTrack; + *(++ptr) = neighbourTrack_features.yerr_PCAonTrack; + *(++ptr) = neighbourTrack_features.zerr_PCAonTrack; + *(++ptr) = neighbourTrack_features.dotprodTrack; + *(++ptr) = neighbourTrack_features.dotprodSeed; + *(++ptr) = neighbourTrack_features.dotprodTrackSeed2D; + *(++ptr) = neighbourTrack_features.dotprodTrackSeed3D; + *(++ptr) = neighbourTrack_features.dotprodTrackSeedVectors2D; + *(++ptr) = neighbourTrack_features.dotprodTrackSeedVectors3D; + *(++ptr) = neighbourTrack_features.pvd_PCAonSeed; + *(++ptr) = neighbourTrack_features.pvd_PCAonTrack; + *(++ptr) = neighbourTrack_features.dist_PCAjetAxis; + *(++ptr) = neighbourTrack_features.dotprod_PCAjetMomenta; + *(++ptr) = neighbourTrack_features.deta_PCAjetDirs; + *(++ptr) = neighbourTrack_features.dphi_PCAjetDirs; + } + +} // namespace btagbtvdeep diff --git a/RecoBTag/TensorFlow/test/test_deepvertex_cfg.py b/RecoBTag/ONNXRuntime/test/test_deep_vertexcomb_cfg.py similarity index 80% rename from RecoBTag/TensorFlow/test/test_deepvertex_cfg.py rename to RecoBTag/ONNXRuntime/test/test_deep_vertexcomb_cfg.py index ca268829ca6e5..cd250cf9f9876 100644 --- a/RecoBTag/TensorFlow/test/test_deepvertex_cfg.py +++ b/RecoBTag/ONNXRuntime/test/test_deep_vertexcomb_cfg.py @@ -48,16 +48,27 @@ svSource = cms.InputTag('slimmedSecondaryVertices'), jetCorrections = ('AK4PFchs', cms.vstring(['L1FastJet', 'L2Relative', 'L3Absolute']), 'None'), btagDiscriminators = [ - 'pfDeepVertexJetTags:probb', + 'pfCombinedSecondaryVertexV2BJetTags', + 'pfDeepCSVJetTags:probudsg', + 'pfDeepCSVJetTags:probb', + 'pfDeepCSVJetTags:probc', + 'pfDeepCSVJetTags:probbb', + 'pfDeepFlavourJetTags:probb', + 'pfDeepFlavourJetTags:probbb', + 'pfDeepFlavourJetTags:problepb', + 'pfDeepFlavourJetTags:probc', + 'pfDeepFlavourJetTags:probuds', + 'pfDeepFlavourJetTags:probg', + 'pfDeepVertexJetTags:probb', + 'pfDeepCombinedJetTags:probb', + ] ) from PhysicsTools.PatAlgos.patInputFiles_cff import filesRelValTTbarPileUpMINIAODSIM process.source.fileNames = filesRelValTTbarPileUpMINIAODSIM -process.source.fileNames = cms.untracked.vstring( - '/store/mc/RunIIFall17MiniAODv2/TTToHadronic_TuneCP5_13TeV-powheg-pythia8/MINIAODSIM/PU2017_12Apr2018_new_pmx_94X_mc2017_realistic_v14-v2/60000/FCC2AFA9-4BBB-E811-B35F-0CC47AFB7D48.root' - #'file:/scratch/lgiannini/bTAG_test_CMSSW/CMSSW_10_1_0_pre3/src/RecoBTag/DeepFlavour/test/0055C65C-E558-E811-AB0E-008CFA582BF4.root') +process.source.fileNames = cms.untracked.vstring('/store/mc/RunIIFall17MiniAODv2/TTToHadronic_TuneCP5_13TeV-powheg-pythia8/MINIAODSIM/PU2017_12Apr2018_new_pmx_94X_mc2017_realistic_v14-v2/60000/FCC2AFA9-4BBB-E811-B35F-0CC47AFB7D48.root') process.maxEvents.input = 10 @@ -67,10 +78,9 @@ process.out.outputCommands.append('keep *_pfDeepCSVTagInfos*_*_*') process.out.outputCommands.append('keep *_pfDeepFlavourTagInfos*_*_*') process.out.outputCommands.append('keep *_pfDeepFlavourJetTags*_*_*') -process.out.outputCommands.append('keep *_pfDeepVertexJetTags*_*_*') process.out.outputCommands.append('keep *_updatedPatJets*_*_*') -process.out.fileName = 'test_deep_vertex_MINIAODSIM_myCfg.root' +process.out.fileName = 'test_deep_vertexcomb_MINIAODSIM.root' # ## # process.options.wantSummary = False ## (to suppress the long output at the end of the job) diff --git a/RecoBTag/TensorFlow/interface/tensor_fillers.h b/RecoBTag/TensorFlow/interface/tensor_fillers.h deleted file mode 100644 index bdc9bcf995489..0000000000000 --- a/RecoBTag/TensorFlow/interface/tensor_fillers.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef RecoBTag_TensorFlow_tensor_fillers_h -#define RecoBTag_TensorFlow_tensor_fillers_h - -#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" -#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h" -#include "DataFormats/BTauReco/interface/DeepDoubleXTagInfo.h" - -namespace btagbtvdeep { - - // Note on setting tensor values: - // Instead of using the more convenient tensor.matrix (etc) methods, - // we can exploit that in the following methods values are set along - // the innermost (= last) axis. Those values are stored contiguously in - // the memory, so it is most performant to get the pointer to the first - // value and use pointer arithmetic to iterate through the next pointers. - - void jet_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepFlavourFeatures& features); - - void jet4vec_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepFlavourFeatures& features); - - void db_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepDoubleXFeatures& features); - - void c_pf_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t c_pf_n, - const btagbtvdeep::ChargedCandidateFeatures& c_pf_features); - - void c_pf_reduced_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t c_pf_n, - const btagbtvdeep::ChargedCandidateFeatures& c_pf_features); - - void n_pf_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t n_pf_n, - const btagbtvdeep::NeutralCandidateFeatures& n_pf_features); - - void sv_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t sv_n, - const btagbtvdeep::SecondaryVertexFeatures& sv_features); - - void sv_reduced_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t sv_n, - const btagbtvdeep::SecondaryVertexFeatures& sv_features); - - void seed_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t seed_n, - const btagbtvdeep::SeedingTrackFeatures& seed_features); - - void neighbourTracks_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t seed_n, - const btagbtvdeep::SeedingTrackFeatures& seed_features); - -} // namespace btagbtvdeep - -#endif diff --git a/RecoBTag/TensorFlow/plugins/BuildFile.xml b/RecoBTag/TensorFlow/plugins/BuildFile.xml deleted file mode 100644 index 1b4348b1c5d05..0000000000000 --- a/RecoBTag/TensorFlow/plugins/BuildFile.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/RecoBTag/TensorFlow/plugins/DeepVertexTFJetTagsProducer.cc b/RecoBTag/TensorFlow/plugins/DeepVertexTFJetTagsProducer.cc deleted file mode 100644 index b46514513a6f2..0000000000000 --- a/RecoBTag/TensorFlow/plugins/DeepVertexTFJetTagsProducer.cc +++ /dev/null @@ -1,316 +0,0 @@ - -#include "FWCore/Framework/interface/Frameworkfwd.h" -#include "FWCore/Framework/interface/stream/EDProducer.h" - -#include "FWCore/Framework/interface/Event.h" -#include "FWCore/Framework/interface/MakerMacros.h" - -#include "FWCore/Framework/interface/makeRefToBaseProdFrom.h" - -#include "FWCore/ParameterSet/interface/ParameterSet.h" -#include "FWCore/Utilities/interface/StreamID.h" - -#include "DataFormats/BTauReco/interface/JetTag.h" - -#include "DataFormats/BTauReco/interface/DeepFlavourTagInfo.h" - -#include "PhysicsTools/TensorFlow/interface/TensorFlow.h" - -#include "RecoBTag/TensorFlow/interface/tensor_fillers.h" - -// Declaration of the data structure that is hold by the edm::GlobalCache. -// In TensorFlow, the computational graph is stored in a stateless graph object which can be shared -// by multiple session instances which handle the initialization of variables related to the graph. -// Following this approach in CMSSW, a graph should be stored in a GlobalCache which can be accessed -// by sessions owned by multiple stream module copies. Instead of using only the plain graph, we -// make use of a cache struct that can be extended in the future if nedded. In addition, the graph -// is protected via std::atomic, which should not affect the performance as it is only accessed in -// the module constructor and not in the actual produce loop. -struct DeepVertexTFCache { - DeepVertexTFCache() : graphDef(nullptr) {} - - std::atomic graphDef; -}; - -class DeepVertexTFJetTagsProducer : public edm::stream::EDProducer> { -public: - explicit DeepVertexTFJetTagsProducer(const edm::ParameterSet&, const DeepVertexTFCache*); - ~DeepVertexTFJetTagsProducer() override; - - static void fillDescriptions(edm::ConfigurationDescriptions&); - - static std::unique_ptr initializeGlobalCache(const edm::ParameterSet&); - static void globalEndJob(const DeepVertexTFCache*); - - enum InputIndexes { - kGlobal = 0, - kSeedingTracks = 1, - kNeighbourTracks = 2, - - }; - - enum OutputIndexes { - kJetFlavour = 0, - - }; - -private: - typedef std::vector TagInfoCollection; - typedef reco::JetTagCollection JetTagCollection; - - void beginStream(edm::StreamID) override {} - void produce(edm::Event&, const edm::EventSetup&) override; - void endStream() override {} - - const edm::EDGetTokenT src_; - std::vector>> flav_pairs_; - std::vector input_names_; - std::vector output_names_; - std::vector lp_names_; - - // session for TF evaluation - tensorflow::Session* session_; - // vector of learning phase tensors, i.e., boolean scalar tensors pointing to false - std::vector lp_tensors_; - // flag to evaluate model batch or jet by jet - bool batch_eval_; - std::string singleThreadPool_; - - const double min_jet_pt_; - const double max_jet_eta_; -}; - -DeepVertexTFJetTagsProducer::DeepVertexTFJetTagsProducer(const edm::ParameterSet& iConfig, - const DeepVertexTFCache* cache) - : src_(consumes(iConfig.getParameter("src"))), - input_names_(iConfig.getParameter>("input_names")), - output_names_(iConfig.getParameter>("output_names")), - lp_names_(iConfig.getParameter>("lp_names")), - session_(nullptr), - batch_eval_(iConfig.getParameter("batch_eval")), - singleThreadPool_(iConfig.getParameter("singleThreadPool")), - min_jet_pt_(iConfig.getParameter("min_jet_pt")), - max_jet_eta_(iConfig.getParameter("max_jet_eta")) - -{ - // get threading config - size_t nThreads = iConfig.getParameter("nThreads"); - - // create the session using the meta graph from the cache - session_ = tensorflow::createSession(cache->graphDef, nThreads); - - // get output names from flav_table - const auto& flav_pset = iConfig.getParameter("flav_table"); - for (const auto& flav_pair : flav_pset.tbl()) { - const auto& flav_name = flav_pair.first; - flav_pairs_.emplace_back(flav_name, flav_pset.getParameter>(flav_name)); - } - - for (const auto& flav_pair : flav_pairs_) { - produces(flav_pair.first); - } - - // flag inputs (required because of batch norm) - // names for the learing phase placeholders (to init and set as false) - for (size_t i = 0; i < lp_names_.size(); i++) { - // create a bool tensor, set its value to false and store it - tensorflow::Tensor t(tensorflow::DT_BOOL, {}); - t.scalar()() = false; - lp_tensors_.push_back(t); - } -} - -DeepVertexTFJetTagsProducer::~DeepVertexTFJetTagsProducer() { - // close and delete the session - if (session_ != nullptr) { - tensorflow::closeSession(session_); - } -} - -void DeepVertexTFJetTagsProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { - // pfDeepVertexJetTags - edm::ParameterSetDescription desc; - desc.add("src", edm::InputTag("pfDeepFlavourTagInfos")); - desc.add>("input_names", - {"input_1", - "input_2", - "input_3", - "input_4", - "input_5", - "input_6", - "input_7", - "input_8", - "input_9", - "input_10", - "input_11", - "input_12"}); - desc.add("graph_path", edm::FileInPath("RecoBTag/Combined/data/DeepVertex/Converted_retraining.pb")); - desc.add>("lp_names", {}); - desc.add>("output_names", {"output_node0"}); ///SIGMOID - { - edm::ParameterSetDescription psd0; - psd0.add>("probb", {0}); - psd0.add>("probc", {1}); - psd0.add>("probuds", {2}); - psd0.add>("probg", {3}); - desc.add("flav_table", psd0); - } - - desc.add("batch_eval", false); - desc.add("min_jet_pt", 15.0); - desc.add("max_jet_eta", 2.5); - desc.add("nThreads", 1); - desc.add("singleThreadPool", "no_threads"); - - descriptions.add("pfDeepVertexJetTags", desc); -} - -std::unique_ptr DeepVertexTFJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) { - // set the tensorflow log level to error - tensorflow::setLogging("3"); - - // get the pb file - std::string pbFile = iConfig.getParameter("graph_path").fullPath(); - - // load the graph def and save it in the cache - DeepVertexTFCache* cache = new DeepVertexTFCache(); - cache->graphDef = tensorflow::loadGraphDef(pbFile); - - return std::unique_ptr(cache); -} - -void DeepVertexTFJetTagsProducer::globalEndJob(const DeepVertexTFCache* cache) { - if (cache->graphDef != nullptr) { - delete cache->graphDef; - } -} - -void DeepVertexTFJetTagsProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { - edm::Handle tag_infos; - iEvent.getByToken(src_, tag_infos); - - // initialize output collection - std::vector> output_tags; - for (std::size_t i = 0; i < flav_pairs_.size(); i++) { - if (!tag_infos->empty()) { - auto jet_ref = tag_infos->begin()->jet(); - output_tags.emplace_back(std::make_unique(edm::makeRefToBaseProdFrom(jet_ref, iEvent))); - } else { - output_tags.emplace_back(std::make_unique()); - } - } - - //changes wrt to DeepFlavour from here - - const int64_t n_jets = tag_infos->size(); - // either all jets or one per batch for the time being - const int64_t n_batch_jets = batch_eval_ ? n_jets : 1; - - std::vector input_sizes{ - {n_batch_jets, 4}, // input_1 - global jet features - - {n_batch_jets, 10, 21}, // input_2 - seeds - {n_batch_jets, 20, 36}, // input_3 - neighbours - {n_batch_jets, 20, 36}, // input_4 - neighbours - {n_batch_jets, 20, 36}, // input_5 - neighbours - {n_batch_jets, 20, 36}, // input_6 - neighbours - {n_batch_jets, 20, 36}, // input_7 - neighbours - {n_batch_jets, 20, 36}, // input_8 - neighbours - {n_batch_jets, 20, 36}, // input_9 - neighbours - {n_batch_jets, 20, 36}, // input_10 - neighbours - {n_batch_jets, 20, 36}, // input_11 - neighbours - {n_batch_jets, 20, 36}, // input_12 - neighbours - - }; - - // create a list of named tensors, i.e. a vector of (string, Tensor) pairs, with proper size to - // prevent element copying that would occur via push_back's - // the default Tensor constructor creates a scalar so this should be fine w.r.t. to memory - tensorflow::NamedTensorList input_tensors; - input_tensors.resize(input_sizes.size()); //+ lp_tensors_.size()); - - // add actual input tensors that hold physics information - for (std::size_t i = 0; i < input_sizes.size(); i++) { - input_tensors[i] = - tensorflow::NamedTensor(input_names_[i], tensorflow::Tensor(tensorflow::DT_FLOAT, input_sizes.at(i))); - } - - // add learning-phase tensors behind them - for (std::size_t i = 0; i < lp_tensors_.size(); i++) { - input_tensors[input_sizes.size() + i] = tensorflow::NamedTensor(lp_names_[i], lp_tensors_[i]); - } - - std::size_t n_batches = n_jets / n_batch_jets; // either 1 or n_jets - - for (std::size_t batch_n = 0; batch_n < n_batches; batch_n++) { - bool run_session = true; //run session can be skipped for unintersting jets only when n_batch_jets==1 - - // tensors have to be zeroed before filling per batch - for (std::size_t i = 0; i < input_sizes.size(); i++) { - input_tensors[i].second.flat().setZero(); - } - - // fill values of the input tensors - for (std::size_t jet_bn = 0; jet_bn < (std::size_t)n_batch_jets; jet_bn++) { - // global jet index (jet_bn is the jet batch index) - std::size_t jet_n = batch_n * n_batch_jets + jet_bn; - - // jet and other global features - const auto& features = tag_infos->at(jet_n).features(); - - //check if jet needs btag with n_batch_jets==1 - if ((features.jet_features.pt < min_jet_pt_ || std::fabs(features.jet_features.eta) > max_jet_eta_) && - n_batch_jets == 1) { - run_session = false; - continue; - } - - jet4vec_tensor_filler(input_tensors.at(kGlobal).second, jet_bn, features); - - // seed features - auto max_seed_n = - std::min(features.seed_features.size(), (std::size_t)input_sizes.at(kSeedingTracks).dim_size(1)); - - for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) { - const auto& seed_features = features.seed_features.at(seed_n); - - seed_tensor_filler(input_tensors.at(kSeedingTracks).second, jet_bn, seed_n, seed_features); - neighbourTracks_tensor_filler( - input_tensors.at(kNeighbourTracks + seed_n).second, jet_bn, seed_n, seed_features); - } - - } //different block - - // run the session - std::vector outputs; - // std::cout <<"Input size" << input_tensors.size() << std::endl; - if (run_session) - tensorflow::run(session_, input_tensors, output_names_, &outputs, singleThreadPool_); - - // set output values for flavour probs - for (std::size_t jet_bn = 0; jet_bn < (std::size_t)n_batch_jets; jet_bn++) { - // global jet index (jet_bn is the jet batch index) - std::size_t jet_n = batch_n * n_batch_jets + jet_bn; - - const auto& jet_ref = tag_infos->at(jet_n).jet(); - for (std::size_t flav_n = 0; flav_n < flav_pairs_.size(); flav_n++) { - const auto& flav_pair = flav_pairs_.at(flav_n); - float o_sum = 0.; - for (const unsigned int& ind : flav_pair.second) { - if (run_session) - o_sum += outputs.at(kJetFlavour).matrix()(jet_bn, ind); - else - o_sum = -2; - } - (*(output_tags.at(flav_n)))[jet_ref] = o_sum; - } - } - } - - for (std::size_t i = 0; i < flav_pairs_.size(); i++) { - iEvent.put(std::move(output_tags[i]), flav_pairs_.at(i).first); - } -} - -//define this as a plug-in -DEFINE_FWK_MODULE(DeepVertexTFJetTagsProducer); diff --git a/RecoBTag/TensorFlow/src/tensor_fillers.cc b/RecoBTag/TensorFlow/src/tensor_fillers.cc deleted file mode 100644 index 4eec2671939c9..0000000000000 --- a/RecoBTag/TensorFlow/src/tensor_fillers.cc +++ /dev/null @@ -1,251 +0,0 @@ -#include "RecoBTag/TensorFlow/interface/tensor_fillers.h" - -namespace btagbtvdeep { - - // Note on setting tensor values: - // Instead of using the more convenient tensor.matrix (etc) methods, - // we can exploit that in the following methods values are set along - // the innermost (= last) axis. Those values are stored contiguously in - // the memory, so it is most performant to get the pointer to the first - // value and use pointer arithmetic to iterate through the next pointers. - - void jet_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepFlavourFeatures& features) { - float* ptr = &tensor.matrix()(jet_n, 0); - - // jet variables - const auto& jet_features = features.jet_features; - *ptr = jet_features.pt; - *(++ptr) = jet_features.eta; - // number of elements in different collections - *(++ptr) = features.c_pf_features.size(); - *(++ptr) = features.n_pf_features.size(); - *(++ptr) = features.sv_features.size(); - *(++ptr) = features.npv; - // variables from ShallowTagInfo - const auto& tag_info_features = features.tag_info_features; - *(++ptr) = tag_info_features.trackSumJetEtRatio; - *(++ptr) = tag_info_features.trackSumJetDeltaR; - *(++ptr) = tag_info_features.vertexCategory; - *(++ptr) = tag_info_features.trackSip2dValAboveCharm; - *(++ptr) = tag_info_features.trackSip2dSigAboveCharm; - *(++ptr) = tag_info_features.trackSip3dValAboveCharm; - *(++ptr) = tag_info_features.trackSip3dSigAboveCharm; - *(++ptr) = tag_info_features.jetNSelectedTracks; - *(++ptr) = tag_info_features.jetNTracksEtaRel; - } - - void jet4vec_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepFlavourFeatures& features) { - float* ptr = &tensor.matrix()(jet_n, 0); - - // jet 4 vector variables - const auto& jet_features = features.jet_features; - *ptr = jet_features.pt; - *(++ptr) = jet_features.eta; - *(++ptr) = jet_features.phi; - *(++ptr) = jet_features.mass; - } - - void db_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - const btagbtvdeep::DeepDoubleXFeatures& features) { - float* ptr = &tensor.tensor()(jet_n, 0, 0); - - // variables from BoostedDoubleSVTagInfo - const auto& tag_info_features = features.tag_info_features; - *ptr = tag_info_features.jetNTracks; - *(++ptr) = tag_info_features.jetNSecondaryVertices; - *(++ptr) = tag_info_features.tau1_trackEtaRel_0; - *(++ptr) = tag_info_features.tau1_trackEtaRel_1; - *(++ptr) = tag_info_features.tau1_trackEtaRel_2; - *(++ptr) = tag_info_features.tau2_trackEtaRel_0; - *(++ptr) = tag_info_features.tau2_trackEtaRel_1; - *(++ptr) = tag_info_features.tau2_trackEtaRel_2; - *(++ptr) = tag_info_features.tau1_flightDistance2dSig; - *(++ptr) = tag_info_features.tau2_flightDistance2dSig; - *(++ptr) = tag_info_features.tau1_vertexDeltaR; - // Note: this variable is not used in the 27-input BDT - // *(++ptr) = tag_info_features.tau2_vertexDeltaR; - *(++ptr) = tag_info_features.tau1_vertexEnergyRatio; - *(++ptr) = tag_info_features.tau2_vertexEnergyRatio; - *(++ptr) = tag_info_features.tau1_vertexMass; - *(++ptr) = tag_info_features.tau2_vertexMass; - *(++ptr) = tag_info_features.trackSip2dSigAboveBottom_0; - *(++ptr) = tag_info_features.trackSip2dSigAboveBottom_1; - *(++ptr) = tag_info_features.trackSip2dSigAboveCharm; - *(++ptr) = tag_info_features.trackSip3dSig_0; - *(++ptr) = tag_info_features.tau1_trackSip3dSig_0; - *(++ptr) = tag_info_features.tau1_trackSip3dSig_1; - *(++ptr) = tag_info_features.trackSip3dSig_1; - *(++ptr) = tag_info_features.tau2_trackSip3dSig_0; - *(++ptr) = tag_info_features.tau2_trackSip3dSig_1; - *(++ptr) = tag_info_features.trackSip3dSig_2; - *(++ptr) = tag_info_features.trackSip3dSig_3; - *(++ptr) = tag_info_features.z_ratio; - } - - void c_pf_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t c_pf_n, - const btagbtvdeep::ChargedCandidateFeatures& c_pf_features) { - float* ptr = &tensor.tensor()(jet_n, c_pf_n, 0); - - *ptr = c_pf_features.btagPf_trackEtaRel; - *(++ptr) = c_pf_features.btagPf_trackPtRel; - *(++ptr) = c_pf_features.btagPf_trackPPar; - *(++ptr) = c_pf_features.btagPf_trackDeltaR; - *(++ptr) = c_pf_features.btagPf_trackPParRatio; - *(++ptr) = c_pf_features.btagPf_trackSip2dVal; - *(++ptr) = c_pf_features.btagPf_trackSip2dSig; - *(++ptr) = c_pf_features.btagPf_trackSip3dVal; - *(++ptr) = c_pf_features.btagPf_trackSip3dSig; - *(++ptr) = c_pf_features.btagPf_trackJetDistVal; - *(++ptr) = c_pf_features.ptrel; - *(++ptr) = c_pf_features.drminsv; - *(++ptr) = c_pf_features.vtx_ass; - *(++ptr) = c_pf_features.puppiw; - *(++ptr) = c_pf_features.chi2; - *(++ptr) = c_pf_features.quality; - } - - void c_pf_reduced_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t c_pf_n, - const btagbtvdeep::ChargedCandidateFeatures& c_pf_features) { - float* ptr = &tensor.tensor()(jet_n, c_pf_n, 0); - - *ptr = c_pf_features.btagPf_trackEtaRel; - *(++ptr) = c_pf_features.btagPf_trackPtRatio; - *(++ptr) = c_pf_features.btagPf_trackPParRatio; - *(++ptr) = c_pf_features.btagPf_trackSip2dVal; - *(++ptr) = c_pf_features.btagPf_trackSip2dSig; - *(++ptr) = c_pf_features.btagPf_trackSip3dVal; - *(++ptr) = c_pf_features.btagPf_trackSip3dSig; - *(++ptr) = c_pf_features.btagPf_trackJetDistVal; - } - - void n_pf_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t n_pf_n, - const btagbtvdeep::NeutralCandidateFeatures& n_pf_features) { - float* ptr = &tensor.tensor()(jet_n, n_pf_n, 0); - - *ptr = n_pf_features.ptrel; - *(++ptr) = n_pf_features.deltaR; - *(++ptr) = n_pf_features.isGamma; - *(++ptr) = n_pf_features.hadFrac; - *(++ptr) = n_pf_features.drminsv; - *(++ptr) = n_pf_features.puppiw; - } - - void sv_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t sv_n, - const btagbtvdeep::SecondaryVertexFeatures& sv_features) { - float* ptr = &tensor.tensor()(jet_n, sv_n, 0); - - *ptr = sv_features.pt; - *(++ptr) = sv_features.deltaR; - *(++ptr) = sv_features.mass; - *(++ptr) = sv_features.ntracks; - *(++ptr) = sv_features.chi2; - *(++ptr) = sv_features.normchi2; - *(++ptr) = sv_features.dxy; - *(++ptr) = sv_features.dxysig; - *(++ptr) = sv_features.d3d; - *(++ptr) = sv_features.d3dsig; - *(++ptr) = sv_features.costhetasvpv; - *(++ptr) = sv_features.enratio; - } - - void sv_reduced_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t sv_n, - const btagbtvdeep::SecondaryVertexFeatures& sv_features) { - float* ptr = &tensor.tensor()(jet_n, sv_n, 0); - - *ptr = sv_features.d3d; - *(++ptr) = sv_features.d3dsig; - } - - void seed_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t seed_n, - const btagbtvdeep::SeedingTrackFeatures& seed_features) { - float* ptr = &tensor.tensor()(jet_n, seed_n, 0); - - *ptr = seed_features.pt; - *(++ptr) = seed_features.eta; - *(++ptr) = seed_features.phi; - *(++ptr) = seed_features.mass; - *(++ptr) = seed_features.dz; - *(++ptr) = seed_features.dxy; - *(++ptr) = seed_features.ip3D; - *(++ptr) = seed_features.sip3D; - *(++ptr) = seed_features.ip2D; - *(++ptr) = seed_features.sip2D; - *(++ptr) = seed_features.signedIp3D; - *(++ptr) = seed_features.signedSip3D; - *(++ptr) = seed_features.signedIp2D; - *(++ptr) = seed_features.signedSip2D; - *(++ptr) = seed_features.trackProbability3D; - *(++ptr) = seed_features.trackProbability2D; - *(++ptr) = seed_features.chi2reduced; - *(++ptr) = seed_features.nPixelHits; - *(++ptr) = seed_features.nHits; - *(++ptr) = seed_features.jetAxisDistance; - *(++ptr) = seed_features.jetAxisDlength; - } - - void neighbourTracks_tensor_filler(tensorflow::Tensor& tensor, - std::size_t jet_n, - std::size_t seed_n, - const btagbtvdeep::SeedingTrackFeatures& seed_features) { - std::vector neighbourTracks_features = seed_features.nearTracks; - - for (unsigned int t_i = 0; t_i < neighbourTracks_features.size(); t_i++) { - float* ptr = &tensor.tensor()(jet_n, t_i, 0); - - *ptr = neighbourTracks_features[t_i].pt; - *(++ptr) = neighbourTracks_features[t_i].eta; - *(++ptr) = neighbourTracks_features[t_i].phi; - *(++ptr) = neighbourTracks_features[t_i].dz; - *(++ptr) = neighbourTracks_features[t_i].dxy; - *(++ptr) = neighbourTracks_features[t_i].mass; - *(++ptr) = neighbourTracks_features[t_i].ip3D; - *(++ptr) = neighbourTracks_features[t_i].sip3D; - *(++ptr) = neighbourTracks_features[t_i].ip2D; - *(++ptr) = neighbourTracks_features[t_i].sip2D; - *(++ptr) = neighbourTracks_features[t_i].distPCA; - *(++ptr) = neighbourTracks_features[t_i].dsigPCA; - *(++ptr) = neighbourTracks_features[t_i].x_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].y_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].z_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].xerr_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].yerr_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].zerr_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].x_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].y_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].z_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].xerr_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].yerr_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].zerr_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].dotprodTrack; - *(++ptr) = neighbourTracks_features[t_i].dotprodSeed; - *(++ptr) = neighbourTracks_features[t_i].dotprodTrackSeed2D; - *(++ptr) = neighbourTracks_features[t_i].dotprodTrackSeed3D; - *(++ptr) = neighbourTracks_features[t_i].dotprodTrackSeedVectors2D; - *(++ptr) = neighbourTracks_features[t_i].dotprodTrackSeedVectors3D; - *(++ptr) = neighbourTracks_features[t_i].pvd_PCAonSeed; - *(++ptr) = neighbourTracks_features[t_i].pvd_PCAonTrack; - *(++ptr) = neighbourTracks_features[t_i].dist_PCAjetAxis; - *(++ptr) = neighbourTracks_features[t_i].dotprod_PCAjetMomenta; - *(++ptr) = neighbourTracks_features[t_i].deta_PCAjetDirs; - *(++ptr) = neighbourTracks_features[t_i].dphi_PCAjetDirs; - } - } - -} // namespace btagbtvdeep