CMS 3D CMS Logo

DeepFlavourONNXJetTagsProducer.cc
Go to the documentation of this file.
3 
6 
8 
11 
13 
15 
17 
18 using namespace cms::Ort;
19 
20 class DeepFlavourONNXJetTagsProducer : public edm::stream::EDProducer<edm::GlobalCache<ONNXRuntime>> {
21 public:
24 
26 
27  static std::unique_ptr<ONNXRuntime> initializeGlobalCache(const edm::ParameterSet&);
28  static void globalEndJob(const ONNXRuntime*);
29 
30 private:
31  typedef std::vector<reco::DeepFlavourTagInfo> TagInfoCollection;
33 
34  void produce(edm::Event&, const edm::EventSetup&) override;
35 
36  void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo& taginfo);
37 
39  std::vector<std::string> flav_names_;
40  std::vector<std::string> input_names_;
41  std::vector<std::string> output_names_;
42 
43  enum InputIndexes { kGlobal = 0, kChargedCandidates = 1, kNeutralCandidates = 2, kVertices = 3, kJetPt = 4 };
44  constexpr static unsigned n_features_global_ = 15;
45  constexpr static unsigned n_cpf_ = 25;
46  constexpr static unsigned n_features_cpf_ = 16;
47  constexpr static unsigned n_npf_ = 25;
48  constexpr static unsigned n_features_npf_ = 6;
49  constexpr static unsigned n_sv_ = 4;
50  constexpr static unsigned n_features_sv_ = 12;
51  constexpr static unsigned n_features_jetpt_ = 1;
52  const static std::vector<unsigned> input_sizes_;
53 
54  // hold the input data
56 };
57 
58 const std::vector<unsigned> DeepFlavourONNXJetTagsProducer::input_sizes_{
59  n_features_global_, n_cpf_* n_features_cpf_, n_npf_* n_features_npf_, n_sv_* n_features_sv_, n_features_jetpt_};
60 
62  const ONNXRuntime* cache)
63  : src_(consumes<TagInfoCollection>(iConfig.getParameter<edm::InputTag>("src"))),
64  flav_names_(iConfig.getParameter<std::vector<std::string>>("flav_names")),
65  input_names_(iConfig.getParameter<std::vector<std::string>>("input_names")),
66  output_names_(iConfig.getParameter<std::vector<std::string>>("output_names")) {
67  // get output names from flav_names
68  for (const auto& flav_name : flav_names_) {
69  produces<JetTagCollection>(flav_name);
70  }
71 
72  assert(input_names_.size() == input_sizes_.size());
73 }
74 
76 
78  // pfDeepFlavourJetTags
80  desc.add<edm::InputTag>("src", edm::InputTag("pfDeepFlavourTagInfos"));
81  desc.add<std::vector<std::string>>("input_names", {"input_1", "input_2", "input_3", "input_4", "input_5"});
82  desc.add<edm::FileInPath>("model_path",
83  edm::FileInPath("RecoBTag/Combined/data/DeepFlavourV03_10X_training/model.onnx"));
84  desc.add<std::vector<std::string>>("output_names", {"ID_pred/Softmax:0"});
85  desc.add<std::vector<std::string>>(
86  "flav_names", std::vector<std::string>{"probb", "probbb", "problepb", "probc", "probuds", "probg"});
87 
88  descriptions.add("pfDeepFlavourJetTags", desc);
89 }
90 
91 std::unique_ptr<ONNXRuntime> DeepFlavourONNXJetTagsProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
92  return std::make_unique<ONNXRuntime>(iConfig.getParameter<edm::FileInPath>("model_path").fullPath());
93 }
94 
96 
99  iEvent.getByToken(src_, tag_infos);
100 
101  std::vector<std::unique_ptr<JetTagCollection>> output_tags;
102  if (!tag_infos->empty()) {
103  // initialize output collection
104  auto jet_ref = tag_infos->begin()->jet();
105  auto ref2prod = edm::makeRefToBaseProdFrom(jet_ref, iEvent);
106  for (std::size_t i = 0; i < flav_names_.size(); i++) {
107  output_tags.emplace_back(std::make_unique<JetTagCollection>(ref2prod));
108  }
109 
110  // init data storage
111  data_.clear();
112  for (const auto& len : input_sizes_) {
113  data_.emplace_back(tag_infos->size() * len, 0);
114  }
115 
116  // convert inputs
117  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
118  const auto& taginfo = (*tag_infos)[jet_n];
119  make_inputs(jet_n, taginfo);
120  }
121 
122  // run prediction
123  auto outputs = globalCache()->run(input_names_, data_, {}, output_names_, tag_infos->size())[0];
124  assert(outputs.size() == flav_names_.size() * tag_infos->size());
125 
126  // get the outputs
127  unsigned i_output = 0;
128  for (unsigned jet_n = 0; jet_n < tag_infos->size(); ++jet_n) {
129  const auto& jet_ref = tag_infos->at(jet_n).jet();
130  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); flav_n++) {
131  (*(output_tags[flav_n]))[jet_ref] = outputs[i_output];
132  ++i_output;
133  }
134  }
135  } else {
136  // create empty output collection
137  for (std::size_t i = 0; i < flav_names_.size(); i++) {
138  output_tags.emplace_back(std::make_unique<JetTagCollection>());
139  }
140  }
141 
142  // put into the event
143  for (std::size_t flav_n = 0; flav_n < flav_names_.size(); ++flav_n) {
144  iEvent.put(std::move(output_tags[flav_n]), flav_names_[flav_n]);
145  }
146 }
147 
149  const auto& features = taginfo.features();
150  float* ptr = nullptr;
151  const float* start = nullptr;
152  unsigned offset = 0;
153 
154  // jet and other global features
155  offset = i_jet * input_sizes_[kGlobal];
156  ptr = &data_[kGlobal][offset];
157  // jet variables
158  const auto& jet_features = features.jet_features;
159  start = ptr;
160  *ptr = jet_features.pt;
161  *(++ptr) = jet_features.eta;
162  // number of elements in different collections
163  *(++ptr) = features.c_pf_features.size();
164  *(++ptr) = features.n_pf_features.size();
165  *(++ptr) = features.sv_features.size();
166  *(++ptr) = features.npv;
167  // variables from ShallowTagInfo
168  const auto& tag_info_features = features.tag_info_features;
169  *(++ptr) = tag_info_features.trackSumJetEtRatio;
170  *(++ptr) = tag_info_features.trackSumJetDeltaR;
171  *(++ptr) = tag_info_features.vertexCategory;
172  *(++ptr) = tag_info_features.trackSip2dValAboveCharm;
173  *(++ptr) = tag_info_features.trackSip2dSigAboveCharm;
174  *(++ptr) = tag_info_features.trackSip3dValAboveCharm;
175  *(++ptr) = tag_info_features.trackSip3dSigAboveCharm;
176  *(++ptr) = tag_info_features.jetNSelectedTracks;
177  *(++ptr) = tag_info_features.jetNTracksEtaRel;
178  assert(start + n_features_global_ - 1 == ptr);
179 
180  // c_pf candidates
181  auto max_c_pf_n = std::min(features.c_pf_features.size(), (std::size_t)25);
182  offset = i_jet * input_sizes_[kChargedCandidates];
183  for (std::size_t c_pf_n = 0; c_pf_n < max_c_pf_n; c_pf_n++) {
184  const auto& c_pf_features = features.c_pf_features.at(c_pf_n);
185  ptr = &data_[kChargedCandidates][offset + c_pf_n * n_features_cpf_];
186  start = ptr;
187  *ptr = c_pf_features.btagPf_trackEtaRel;
188  *(++ptr) = c_pf_features.btagPf_trackPtRel;
189  *(++ptr) = c_pf_features.btagPf_trackPPar;
190  *(++ptr) = c_pf_features.btagPf_trackDeltaR;
191  *(++ptr) = c_pf_features.btagPf_trackPParRatio;
192  *(++ptr) = c_pf_features.btagPf_trackSip2dVal;
193  *(++ptr) = c_pf_features.btagPf_trackSip2dSig;
194  *(++ptr) = c_pf_features.btagPf_trackSip3dVal;
195  *(++ptr) = c_pf_features.btagPf_trackSip3dSig;
196  *(++ptr) = c_pf_features.btagPf_trackJetDistVal;
197  *(++ptr) = c_pf_features.ptrel;
198  *(++ptr) = c_pf_features.drminsv;
199  *(++ptr) = c_pf_features.vtx_ass;
200  *(++ptr) = c_pf_features.puppiw;
201  *(++ptr) = c_pf_features.chi2;
202  *(++ptr) = c_pf_features.quality;
203  assert(start + n_features_cpf_ - 1 == ptr);
204  }
205 
206  // n_pf candidates
207  auto max_n_pf_n = std::min(features.n_pf_features.size(), (std::size_t)25);
208  offset = i_jet * input_sizes_[kNeutralCandidates];
209  for (std::size_t n_pf_n = 0; n_pf_n < max_n_pf_n; n_pf_n++) {
210  const auto& n_pf_features = features.n_pf_features.at(n_pf_n);
211  ptr = &data_[kNeutralCandidates][offset + n_pf_n * n_features_npf_];
212  start = ptr;
213  *ptr = n_pf_features.ptrel;
214  *(++ptr) = n_pf_features.deltaR;
215  *(++ptr) = n_pf_features.isGamma;
216  *(++ptr) = n_pf_features.hadFrac;
217  *(++ptr) = n_pf_features.drminsv;
218  *(++ptr) = n_pf_features.puppiw;
219  assert(start + n_features_npf_ - 1 == ptr);
220  }
221 
222  // sv candidates
223  auto max_sv_n = std::min(features.sv_features.size(), (std::size_t)4);
224  offset = i_jet * input_sizes_[kVertices];
225  for (std::size_t sv_n = 0; sv_n < max_sv_n; sv_n++) {
226  const auto& sv_features = features.sv_features.at(sv_n);
227  ptr = &data_[kVertices][offset + sv_n * n_features_sv_];
228  start = ptr;
229  *ptr = sv_features.pt;
230  *(++ptr) = sv_features.deltaR;
231  *(++ptr) = sv_features.mass;
232  *(++ptr) = sv_features.ntracks;
233  *(++ptr) = sv_features.chi2;
234  *(++ptr) = sv_features.normchi2;
235  *(++ptr) = sv_features.dxy;
236  *(++ptr) = sv_features.dxysig;
237  *(++ptr) = sv_features.d3d;
238  *(++ptr) = sv_features.d3dsig;
239  *(++ptr) = sv_features.costhetasvpv;
240  *(++ptr) = sv_features.enratio;
241  assert(start + n_features_sv_ - 1 == ptr);
242  }
243 
244  // last input: jet pt
245  offset = i_jet * input_sizes_[kJetPt];
246  data_[kJetPt][offset] = features.jet_features.pt;
247 }
248 
249 //define this as a plug-in
const Features & features() const
Definition: start.py:1
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
taginfo
Definition: lumiTag.py:81
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
static void fillDescriptions(edm::ConfigurationDescriptions &)
void make_inputs(unsigned i_jet, const reco::DeepFlavourTagInfo &taginfo)
void produce(edm::Event &, const edm::EventSetup &) override
std::vector< std::vector< float > > FloatArrays
Definition: ONNXRuntime.h:23
int iEvent
Definition: GenABIO.cc:224
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
T min(T a, T b)
Definition: MathUtil.h:58
ParameterDescriptionBase * add(U const &iLabel, T const &value)
const edm::EDGetTokenT< TagInfoCollection > src_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
static std::unique_ptr< ONNXRuntime > initializeGlobalCache(const edm::ParameterSet &)
RefToBaseProd< T > makeRefToBaseProdFrom(RefToBase< T > const &iRef, Event const &iEvent)
static const std::vector< unsigned > input_sizes_
HLT enums.
def cache(function)
Definition: utilities.py:3
DeepFlavourONNXJetTagsProducer(const edm::ParameterSet &, const ONNXRuntime *)
std::vector< reco::DeepFlavourTagInfo > TagInfoCollection
def move(src, dest)
Definition: eostools.py:511
#define constexpr
static void globalEndJob(const ONNXRuntime *)