CMS 3D CMS Logo

DeepCombinedONNXJetTagsProducer.cc
Go to the documentation of this file.
3 
6 
8 
11 
13 
15 
17 
20 
21 using namespace cms::Ort;
22 
23 class DeepCombinedONNXJetTagsProducer : 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 {
50  kGlobal = 0,
51  kChargedCandidates = 1,
52  kNeutralCandidates = 2,
53  kVertices = 3,
54  kGlobal1 = 4,
55  kSeedingTracks = 5,
56  kNeighbourTracks = 6
57  };
58  const static unsigned n_features_global_ = deepflavour::n_features_global;
59  const static unsigned n_cpf_ = deepflavour::n_cpf;
60  const static unsigned n_features_cpf_ = deepflavour::n_features_cpf;
61  const static unsigned n_npf_ = deepflavour::n_npf;
62  const static unsigned n_features_npf_ = deepflavour::n_features_npf;
63  const static unsigned n_sv_ = deepflavour::n_sv;
64  const static unsigned n_features_sv_ = deepflavour::n_features_sv;
65  const static unsigned n_features_global1_ = deepvertex::n_features_global;
66  const static unsigned n_seed_ = deepvertex::n_seed;
67  const static unsigned n_features_seed_ = deepvertex::n_features_seed;
68  const static unsigned n_neighbor_ = deepvertex::n_neighbor;
69  const static unsigned n_features_neighbor_ = deepvertex::n_features_neighbor;
70 
71  const static std::vector<unsigned> input_sizes_;
72 
73  // hold the input data
75 };
76 
77 const std::vector<unsigned> DeepCombinedONNXJetTagsProducer::input_sizes_{n_features_global_,
78  n_cpf_* n_features_cpf_,
79  n_npf_* n_features_npf_,
80  n_sv_* n_features_sv_,
81  n_features_global1_,
82  n_seed_* n_features_seed_,
83  n_neighbor_* n_features_neighbor_,
84  n_neighbor_* n_features_neighbor_,
85  n_neighbor_* n_features_neighbor_,
86  n_neighbor_* n_features_neighbor_,
87  n_neighbor_* n_features_neighbor_,
88  n_neighbor_* n_features_neighbor_,
89  n_neighbor_* n_features_neighbor_,
90  n_neighbor_* n_features_neighbor_,
91  n_neighbor_* n_features_neighbor_,
92  n_neighbor_* n_features_neighbor_};
93 
95  const ONNXRuntime* cache)
96  : src_(consumes<TagInfoCollection>(iConfig.getParameter<edm::InputTag>("src"))),
97  flav_names_(iConfig.getParameter<std::vector<std::string>>("flav_names")),
98  input_names_(iConfig.getParameter<std::vector<std::string>>("input_names")),
99  output_names_(iConfig.getParameter<std::vector<std::string>>("output_names")),
100  min_jet_pt_(iConfig.getParameter<double>("min_jet_pt")),
101  max_jet_eta_(iConfig.getParameter<double>("max_jet_eta")) {
102  // get output names from flav_names
103  for (const auto& flav_name : flav_names_) {
104  produces<JetTagCollection>(flav_name);
105  }
106 
107  assert(input_names_.size() == input_sizes_.size());
108 }
109 
111 
113  // pfDeepFlavourJetTags
115  desc.add<edm::InputTag>("src", edm::InputTag("pfDeepFlavourTagInfos"));
116  desc.add<std::vector<std::string>>("input_names",
117  {"input_1_DFla",
118  "input_2_DFla",
119  "input_3_DFla",
120  "input_4_DFla",
121  "input_1",
122  "input_2",
123  "input_3",
124  "input_4",
125  "input_5",
126  "input_6",
127  "input_7",
128  "input_8",
129  "input_9",
130  "input_10",
131  "input_11",
132  "input_12"});
133  desc.add<edm::FileInPath>("model_path",
134  edm::FileInPath("RecoBTag/Combined/data/DeepVertex/phase1_deepvertexcombined.onnx"));
135  desc.add<std::vector<std::string>>("output_names", {"dense_13"});
136  desc.add<std::vector<std::string>>("flav_names", std::vector<std::string>{"probb", "probc", "probuds", "probg"});
137  desc.add<double>("min_jet_pt", 15.0);
138  desc.add<double>("max_jet_eta", 2.5);
139 
140  descriptions.add("pfDeepCombinedJetTags", desc);
141 }
142 
143 std::unique_ptr<ONNXRuntime> DeepCombinedONNXJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
144  return std::make_unique<ONNXRuntime>(iConfig.getParameter<edm::FileInPath>("model_path").fullPath());
145 }
146 
148 
151  iEvent.getByToken(src_, tag_infos);
152 
153  data_.clear();
154 
155  std::vector<std::unique_ptr<JetTagCollection>> output_tags;
156  if (!tag_infos->empty()) {
157  unsigned good_taginfo_count = 0;
158  std::vector<bool> good_taginfo_jets(tag_infos->size(), false);
159  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
160  const auto& jet_ref = (*tag_infos)[jet_n].jet();
161  if (jet_ref->pt() > min_jet_pt_ && std::fabs(jet_ref->eta()) < max_jet_eta_) {
162  good_taginfo_count++;
163  good_taginfo_jets[jet_n] = true;
164  }
165  }
166 
167  // init data storage w correct size
168  for (const auto& len : input_sizes_) {
169  data_.emplace_back(good_taginfo_count * len, 0);
170  }
171 
172  // initialize output collection
173  auto jet_ref = tag_infos->begin()->jet();
174  auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent);
175  for (std::size_t i = 0; i < flav_names_.size(); i++) {
176  output_tags.emplace_back(std::make_unique<JetTagCollection>(ref2prod));
177  }
178 
179  // convert inputs
180  unsigned inputs_done_count = 0;
181  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
182  if (good_taginfo_jets[jet_n]) {
183  const auto& taginfo = (*tag_infos)[jet_n];
184  make_inputs(inputs_done_count, taginfo);
185  inputs_done_count++;
186  }
187  }
188 
189  // run prediction
190  assert(inputs_done_count == good_taginfo_count);
191  const auto outputs = globalCache()->run(input_names_, data_, {}, output_names_, good_taginfo_count)[0];
192  assert(outputs.size() == flav_names_.size() * good_taginfo_count);
193 
194  // get the outputs
195  unsigned i_output = 0;
196  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
197  const auto& jet_ref = (*tag_infos)[jet_n].jet();
198  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) {
199  if (good_taginfo_jets[jet_n]) {
200  (*(output_tags[flav_n]))[jet_ref] = outputs[i_output];
201  ++i_output;
202  } else {
203  (*(output_tags[flav_n]))[jet_ref] = -2;
204  }
205  }
206  }
207  } else {
208  // create empty output collection
209  for (std::size_t i = 0; i < flav_names_.size(); i++) {
210  output_tags.emplace_back(std::make_unique<JetTagCollection>());
211  }
212  }
213 
214  // put into the event
215  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) {
216  iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]);
217  }
218 }
219 
221  const auto& features = taginfo.features();
222  float* ptr = nullptr;
223  const float* start = nullptr;
224  unsigned offset = 0;
225 
226  // jet and other global features
227  offset = i_jet * input_sizes_[kGlobal];
228  ptr = &data_[kGlobal][offset];
229  start = ptr;
231  assert(start + n_features_global_ - 1 == ptr);
232 
233  // c_pf candidates
234  auto max_c_pf_n = std::min(features.c_pf_features.size(), (std::size_t)n_cpf_);
235  offset = i_jet * input_sizes_[kChargedCandidates];
236  for (std::size_t c_pf_n = 0; c_pf_n < max_c_pf_n; c_pf_n++) {
237  const auto& c_pf_features = features.c_pf_features[c_pf_n];
238  ptr = &data_[kChargedCandidates][offset + c_pf_n * n_features_cpf_];
239  start = ptr;
240  cpf_tensor_filler(ptr, c_pf_features);
241  assert(start + n_features_cpf_ - 1 == ptr);
242  }
243 
244  // n_pf candidates
245  auto max_n_pf_n = std::min(features.n_pf_features.size(), (std::size_t)n_npf_);
246  offset = i_jet * input_sizes_[kNeutralCandidates];
247  for (std::size_t n_pf_n = 0; n_pf_n < max_n_pf_n; n_pf_n++) {
248  const auto& n_pf_features = features.n_pf_features[n_pf_n];
249  ptr = &data_[kNeutralCandidates][offset + n_pf_n * n_features_npf_];
250  start = ptr;
251  npf_tensor_filler(ptr, n_pf_features);
252  assert(start + n_features_npf_ - 1 == ptr);
253  }
254 
255  // sv candidates
256  auto max_sv_n = std::min(features.sv_features.size(), (std::size_t)n_sv_);
257  offset = i_jet * input_sizes_[kVertices];
258  for (std::size_t sv_n = 0; sv_n < max_sv_n; sv_n++) {
259  const auto& sv_features = features.sv_features[sv_n];
260  ptr = &data_[kVertices][offset + sv_n * n_features_sv_];
261  start = ptr;
262  sv_tensor_filler(ptr, sv_features);
263  assert(start + n_features_sv_ - 1 == ptr);
264  }
265 
266  // jet variables
267  offset = i_jet * input_sizes_[kGlobal1];
268  const auto& jet_features = features.jet_features;
269  ptr = &data_[kGlobal1][offset];
270  start = ptr;
271  jet4vec_tensor_filler(ptr, jet_features);
272  assert(start + n_features_global1_ - 1 == ptr);
273 
274  // seeds
275  auto max_seed_n = std::min(features.seed_features.size(), (std::size_t)n_seed_);
276  offset = i_jet * input_sizes_[kSeedingTracks];
277  for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) {
278  const auto& seed_features = features.seed_features[seed_n];
279  ptr = &data_[kSeedingTracks][offset + seed_n * n_features_seed_];
280  start = ptr;
281  seedTrack_tensor_filler(ptr, seed_features);
282  assert(start + n_features_seed_ - 1 == ptr);
283  }
284 
285  // neighbours
286  offset = i_jet * input_sizes_[kNeighbourTracks];
287  for (std::size_t seed_n = 0; seed_n < max_seed_n; seed_n++) {
288  const auto& neighbourTracks_features = features.seed_features[seed_n].nearTracks;
289  auto max_neighbour_n = std::min(neighbourTracks_features.size(), (std::size_t)n_neighbor_);
290  for (std::size_t neighbour_n = 0; neighbour_n < max_neighbour_n; neighbour_n++) {
291  ptr = &data_[kNeighbourTracks + seed_n][offset + neighbour_n * n_features_neighbor_];
292  start = ptr;
293  neighbourTrack_tensor_filler(ptr, neighbourTracks_features[neighbour_n]);
294  assert(start + n_features_neighbor_ - 1 == ptr);
295  }
296  }
297 }
298 
299 //define this as a plug-in
const Features & features() const
Definition: start.py:1
void npf_tensor_filler(float *&ptr, const btagbtvdeep::NeutralCandidateFeatures &n_pf_features)
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
void cpf_tensor_filler(float *&ptr, const btagbtvdeep::ChargedCandidateFeatures &c_pf_features)
taginfo
Definition: lumiTag.py:81
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
std::vector< reco::DeepFlavourTagInfo > TagInfoCollection
constexpr unsigned n_features_cpf
Definition: tensor_configs.h:9
std::vector< std::vector< float > > FloatArrays
Definition: ONNXRuntime.h:23
void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo &taginfo)
constexpr unsigned n_neighbor
constexpr unsigned n_features_global
constexpr unsigned n_sv
int iEvent
Definition: GenABIO.cc:224
static const std::vector< unsigned > input_sizes_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const edm::EDGetTokenT< TagInfoCollection > src_
constexpr unsigned n_features_sv
void sv_tensor_filler(float *&ptr, const btagbtvdeep::SecondaryVertexFeatures &sv_features)
void produce(edm::Event &, const edm::EventSetup &) override
constexpr unsigned n_features_npf
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
void jet_tensor_filler(float *&ptr, const btagbtvdeep::DeepFlavourFeatures &features)
constexpr unsigned n_features_global
Definition: tensor_configs.h:6
constexpr unsigned n_features_seed
static void globalEndJob(const ONNXRuntime *)
constexpr unsigned n_cpf
Definition: tensor_configs.h:8
static void fillDescriptions(edm::ConfigurationDescriptions &)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
static std::unique_ptr< ONNXRuntime > initializeGlobalCache(const edm::ParameterSet &)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
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
DeepCombinedONNXJetTagsProducer(const edm::ParameterSet &, const ONNXRuntime *)
constexpr unsigned n_npf
def move(src, dest)
Definition: eostools.py:511
void jet4vec_tensor_filler(float *&ptr, const btagbtvdeep::JetFeatures &jet_features)