CMS 3D CMS Logo

DeepVertexONNXJetTagsProducer.cc
Go to the documentation of this file.
3 
6 
8 
11 
13 
15 
17 
20 
21 using namespace cms::Ort;
22 
23 class DeepVertexONNXJetTagsProducer : public edm::stream::EDProducer<edm::GlobalCache<ONNXRuntime>> {
24 public:
27 
29 
30  static std::unique_ptr<ONNXRuntime> initializeGlobalCache(const edm::ParameterSet&);
31  static void globalEndJob(const ONNXRuntime*);
32 
33 private:
34  typedef std::vector<reco::DeepFlavourTagInfo> TagInfoCollection;
36 
37  void produce(edm::Event&, const edm::EventSetup&) override;
38 
39  void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo);
40 
42  std::vector<std::string> flav_names_;
43  std::vector<std::string> input_names_;
44  std::vector<std::string> output_names_;
45 
46  const double min_jet_pt_;
47  const double max_jet_eta_;
48 
49  enum InputIndexes { kGlobal = 0, kSeedingTracks = 1, kNeighbourTracks = 2 };
50  const static unsigned n_features_global_ = deepvertex::n_features_global;
51  const static unsigned n_seed_ = deepvertex::n_seed;
52  const static unsigned n_features_seed_ = deepvertex::n_features_seed;
53  const static unsigned n_neighbor_ = deepvertex::n_neighbor;
54  const static unsigned n_features_neighbor_ = deepvertex::n_features_neighbor;
55 
56  const static std::vector<unsigned> input_sizes_;
57 
58  // hold the input data
60 };
61 
62 const std::vector<unsigned> DeepVertexONNXJetTagsProducer::input_sizes_{n_features_global_,
63  n_seed_* n_features_seed_,
64  n_neighbor_* n_features_neighbor_,
65  n_neighbor_* n_features_neighbor_,
66  n_neighbor_* n_features_neighbor_,
67  n_neighbor_* n_features_neighbor_,
68  n_neighbor_* n_features_neighbor_,
69  n_neighbor_* n_features_neighbor_,
70  n_neighbor_* n_features_neighbor_,
71  n_neighbor_* n_features_neighbor_,
72  n_neighbor_* n_features_neighbor_,
73  n_neighbor_* n_features_neighbor_};
74 
76  : src_(consumes<TagInfoCollection>(iConfig.getParameter<edm::InputTag>("src"))),
77  flav_names_(iConfig.getParameter<std::vector<std::string>>("flav_names")),
78  input_names_(iConfig.getParameter<std::vector<std::string>>("input_names")),
79  output_names_(iConfig.getParameter<std::vector<std::string>>("output_names")),
80  min_jet_pt_(iConfig.getParameter<double>("min_jet_pt")),
81  max_jet_eta_(iConfig.getParameter<double>("max_jet_eta")) {
82  // get output names from flav_names
83  for (const auto& flav_name : flav_names_) {
84  produces<JetTagCollection>(flav_name);
85  }
86 
87  assert(input_names_.size() == input_sizes_.size());
88 }
89 
91 
93  // pfDeepFlavourJetTags
95  desc.add<edm::InputTag>("src", edm::InputTag("pfDeepFlavourTagInfos"));
96  desc.add<std::vector<std::string>>("input_names",
97  {"input_1",
98  "input_2",
99  "input_3",
100  "input_4",
101  "input_5",
102  "input_6",
103  "input_7",
104  "input_8",
105  "input_9",
106  "input_10",
107  "input_11",
108  "input_12"});
109  desc.add<edm::FileInPath>("model_path", edm::FileInPath("RecoBTag/Combined/data/DeepVertex/phase1_deepvertex.onnx"));
110  desc.add<std::vector<std::string>>("output_names", {"dense_6"});
111  desc.add<std::vector<std::string>>("flav_names", std::vector<std::string>{"probb", "probc", "probuds", "probg"});
112  desc.add<double>("min_jet_pt", 15.0);
113  desc.add<double>("max_jet_eta", 2.5);
114 
115  descriptions.add("pfDeepVertexJetTags", desc);
116 }
117 
118 std::unique_ptr<ONNXRuntime> DeepVertexONNXJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
119  return std::make_unique<ONNXRuntime>(iConfig.getParameter<edm::FileInPath>("model_path").fullPath());
120 }
121 
123 
126  iEvent.getByToken(src_, tag_infos);
127 
128  data_.clear();
129 
130  std::vector<std::unique_ptr<JetTagCollection>> output_tags;
131  if (!tag_infos->empty()) {
132  unsigned good_taginfo_count = 0;
133  std::vector<bool> good_taginfo_jets(tag_infos->size(), false);
134  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
135  const auto& jet_ref = (*tag_infos)[jet_n].jet();
136  if (jet_ref->pt() > min_jet_pt_ && std::fabs(jet_ref->eta()) < max_jet_eta_) {
137  good_taginfo_count++;
138  good_taginfo_jets[jet_n] = true;
139  }
140  }
141 
142  // init data storage w correct size
143  for (const auto& len : input_sizes_) {
144  data_.emplace_back(good_taginfo_count * len, 0);
145  }
146 
147  // initialize output collection
148  auto jet_ref = tag_infos->begin()->jet();
149  auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent);
150  for (std::size_t i = 0; i < flav_names_.size(); i++) {
151  output_tags.emplace_back(std::make_unique<JetTagCollection>(ref2prod));
152  }
153 
154  // convert inputs
155  unsigned inputs_done_count = 0;
156  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
157  if (good_taginfo_jets[jet_n]) {
158  const auto& taginfo = (*tag_infos)[jet_n];
159  make_inputs(inputs_done_count, taginfo);
160  inputs_done_count++;
161  }
162  }
163 
164  // run prediction
165  assert(inputs_done_count == good_taginfo_count);
166  const auto outputs = globalCache()->run(input_names_, data_, {}, output_names_, good_taginfo_count)[0];
167  assert(outputs.size() == flav_names_.size() * good_taginfo_count);
168 
169  // get the outputs
170  unsigned i_output = 0;
171  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
172  const auto& jet_ref = (*tag_infos)[jet_n].jet();
173  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) {
174  if (good_taginfo_jets[jet_n]) {
175  (*(output_tags[flav_n]))[jet_ref] = outputs[i_output];
176  ++i_output;
177  } else {
178  (*(output_tags[flav_n]))[jet_ref] = -2;
179  }
180  }
181  }
182  } else {
183  // create empty output collection
184  for (std::size_t i = 0; i < flav_names_.size(); i++) {
185  output_tags.emplace_back(std::make_unique<JetTagCollection>());
186  }
187  }
188 
189  // put into the event
190  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) {
191  iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]);
192  }
193 }
194 
196  const auto& features = taginfo.features();
197  float* ptr = nullptr;
198  const float* start = nullptr;
199  unsigned offset = 0;
200 
201  // jet variables
202  offset = i_jet * input_sizes_[kGlobal];
203  const auto& jet_features = features.jet_features;
204  ptr = &data_[kGlobal][offset];
205  start = ptr;
206  jet4vec_tensor_filler(ptr, jet_features);
207  assert(start + n_features_global_ - 1 == ptr);
208 
209  // seeds
210  auto max_seed_n = std::min(features.seed_features.size(), (std::size_t)n_seed_);
211  offset = i_jet * input_sizes_[kSeedingTracks];
212  for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) {
213  const auto& seed_features = features.seed_features[seed_n];
214  ptr = &data_[kSeedingTracks][offset + seed_n * n_features_seed_];
215  start = ptr;
216  seedTrack_tensor_filler(ptr, seed_features);
217  assert(start + n_features_seed_ - 1 == ptr);
218  }
219 
220  // neighbours
221  offset = i_jet * input_sizes_[kNeighbourTracks];
222  for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) {
223  const auto& neighbourTracks_features = features.seed_features[seed_n].nearTracks;
224  auto max_neighbour_n = std::min(neighbourTracks_features.size(), (std::size_t)n_neighbor_);
225  for (std::size_t neighbour_n = 0; neighbour_n < max_neighbour_n; neighbour_n++) {
226  ptr = &data_[kNeighbourTracks + seed_n][offset + neighbour_n * n_features_neighbor_];
227  start = ptr;
228  neighbourTrack_tensor_filler(ptr, neighbourTracks_features[neighbour_n]);
229  assert(start + n_features_neighbor_ - 1 == ptr);
230  }
231  }
232 }
233 
234 //define this as a plug-in
const Features & features() const
Definition: start.py:1
T getParameter(std::string const &) const
const edm::EDGetTokenT< TagInfoCollection > src_
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
void produce(edm::Event &, const edm::EventSetup &) override
static void fillDescriptions(edm::ConfigurationDescriptions &)
taginfo
Definition: lumiTag.py:81
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
static const std::vector< unsigned > input_sizes_
std::vector< std::vector< float > > FloatArrays
Definition: ONNXRuntime.h:23
constexpr unsigned n_neighbor
constexpr unsigned n_features_global
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
void neighbourTrack_tensor_filler(float *&ptr, const btagbtvdeep::TrackPairFeatures &neighbourTrack_features)
T min(T a, T b)
Definition: MathUtil.h:58
ParameterDescriptionBase * add(U const &iLabel, T const &value)
constexpr unsigned n_features_neighbor
constexpr unsigned n_features_seed
static std::unique_ptr< ONNXRuntime > initializeGlobalCache(const edm::ParameterSet &)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
std::vector< reco::DeepFlavourTagInfo > TagInfoCollection
void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo &taginfo)
DeepVertexONNXJetTagsProducer(const edm::ParameterSet &, const ONNXRuntime *)
RefToBaseProd< T > makeRefToBaseProdFrom(RefToBase< T > const &iRef, Event const &iEvent)
HLT enums.
void seedTrack_tensor_filler(float *&ptr, const btagbtvdeep::SeedingTrackFeatures &seed_features)
def cache(function)
Definition: utilities.py:3
constexpr unsigned n_seed
def move(src, dest)
Definition: eostools.py:511
void jet4vec_tensor_filler(float *&ptr, const btagbtvdeep::JetFeatures &jet_features)
static void globalEndJob(const ONNXRuntime *)