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