CMS 3D CMS Logo

L1NNTauProducer.cc
Go to the documentation of this file.
2 #include <TLorentzVector.h>
3 #include <cmath>
4 #include <vector>
5 
11 
16 
17 #include "ap_int.h"
18 #include "ap_fixed.h"
19 
20 using namespace l1t;
21 
22 class L1NNTauProducer : public edm::stream::EDProducer<edm::GlobalCache<tensorflow::SessionCache>> {
23 public:
25  ~L1NNTauProducer() override;
26 
27  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
28  static std::unique_ptr<tensorflow::SessionCache> initializeGlobalCache(const edm::ParameterSet&);
29  static void globalEndJob(const tensorflow::SessionCache*){};
30 
31 private:
32  // There is te software and hardware emulator for the tau, default is the Hardware.
33  std::unique_ptr<TauNNId> fTauNNId_;
34  std::unique_ptr<TauNNIdHW> fTauNNIdHW_; // Default
35 
36  void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
37  void process_SW(const l1t::PFCandidateCollection& parts, std::unique_ptr<l1t::PFTauCollection>& iTaus);
38  void process_HW(const l1t::PFCandidateCollection& parts, std::unique_ptr<l1t::PFTauCollection>& iTaus);
39  void makeTau_HW(const l1t::PFCandidate& seed,
41  std::unique_ptr<l1t::PFTauCollection>& iTaus);
42 
43  void addTau(const l1t::PFCandidate& iCand,
44  const l1t::PFCandidateCollection& iParts,
45  std::unique_ptr<PFTauCollection>& outputTaus);
46 
47  double fSeedPt_;
48  double fConeSize_;
49  double fTauSize_;
50  int fMaxTaus_;
52  const bool fHW;
53  const bool fEMSeed;
54  const bool fDebug;
56 };
57 
58 static constexpr float track_trigger_eta_max = 2.5;
59 
61  : fSeedPt_(cfg.getParameter<double>("seedpt")),
62  fConeSize_(cfg.getParameter<double>("conesize")),
63  fTauSize_(cfg.getParameter<double>("tausize")),
64  fMaxTaus_(cfg.getParameter<int>("maxtaus")),
65  fNParticles_(cfg.getParameter<int>("nparticles")),
66  fHW(cfg.getParameter<bool>("HW")),
67  fEMSeed(cfg.getParameter<bool>("emseed")),
68  fDebug(cfg.getParameter<bool>("debug")),
69  fL1PFToken_(consumes<vector<l1t::PFCandidate>>(cfg.getParameter<edm::InputTag>("L1PFObjects"))) {
70  std::string lNNFile = cfg.getParameter<std::string>("NNFileName"); //,"L1Trigger/Phase2L1Taus/data/tau_3layer.pb");
71  if (fHW) {
72  fTauNNIdHW_ = std::make_unique<TauNNIdHW>();
73  fTauNNIdHW_->initialize("input_1:0", fNParticles_);
74  } else {
75  fTauNNId_ = std::make_unique<TauNNId>(lNNFile.find("v0") == std::string::npos ? "input_1:0" : "dense_1_input:0",
76  cache->getSession(),
77  lNNFile,
78  fNParticles_);
79  }
80  produces<l1t::PFTauCollection>("L1PFTausNN");
81 }
82 
83 std::unique_ptr<tensorflow::SessionCache> L1NNTauProducer::initializeGlobalCache(const edm::ParameterSet& cfg) {
85  std::string graphPath = edm::FileInPath(cfg.getParameter<std::string>("NNFileName")).fullPath();
86  return std::make_unique<tensorflow::SessionCache>(graphPath);
87 }
88 
91  iEvent.getByToken(fL1PFToken_, l1PFCandidates);
92  auto lTaus = std::make_unique<l1t::PFTauCollection>();
93 
94  if (fHW) {
95  process_HW(*l1PFCandidates, lTaus);
96  } else {
97  process_SW(*l1PFCandidates, lTaus);
98  }
99 
100  if (lTaus->empty()) {
101  PFTau dummy;
102  lTaus->push_back(dummy);
103  }
104  std::sort(lTaus->begin(), lTaus->end(), [](l1t::PFTau i, l1t::PFTau j) { return (i.pt() > j.pt()); });
105  iEvent.put(std::move(lTaus), "L1PFTausNN");
106 }
108  std::unique_ptr<l1t::PFTauCollection>& iTaus) {
109  std::vector<unique_ptr<l1t::PFCandidate>> pfChargedHadrons;
110  std::vector<unique_ptr<l1t::PFCandidate>> pfChargedHadrons_sort_v;
111  std::vector<unique_ptr<l1t::PFCandidate>> pfChargedHadrons_seeds_v;
112  for (const auto& l1PFCand : parts)
113  if ((l1PFCand.id() == l1t::PFCandidate::ChargedHadron || l1PFCand.id() == l1t::PFCandidate::Electron) &&
114  std::abs(l1PFCand.eta()) < track_trigger_eta_max)
115  pfChargedHadrons_sort_v.push_back(std::make_unique<l1t::PFCandidate>(l1PFCand));
116 
117  if (pfChargedHadrons_sort_v.empty())
118  return;
119  std::sort(
120  pfChargedHadrons_sort_v.begin(),
121  pfChargedHadrons_sort_v.end(),
122  [](std::unique_ptr<l1t::PFCandidate>& i, std::unique_ptr<l1t::PFCandidate>& j) { return (i->pt() > j->pt()); });
123 
124  pfChargedHadrons_seeds_v.push_back(std::move(pfChargedHadrons_sort_v[0]));
125  for (unsigned int i0 = 1; i0 < pfChargedHadrons_sort_v.size(); i0++) {
126  bool pMatch = false;
127  for (unsigned int i1 = 0; i1 < pfChargedHadrons_seeds_v.size(); i1++) {
128  if (reco::deltaR2(*(pfChargedHadrons_seeds_v[i1]), *(pfChargedHadrons_sort_v[i0])) < fConeSize_ * fConeSize_)
129  pMatch = true;
130  }
131  if (pMatch)
132  continue;
133  pfChargedHadrons_seeds_v.push_back(std::move(pfChargedHadrons_sort_v[i0]));
134  if (int(pfChargedHadrons_seeds_v.size()) > fMaxTaus_ - 1)
135  break;
136  }
137  for (unsigned int i0 = 0; i0 < pfChargedHadrons_seeds_v.size(); i0++) {
138  addTau(*(pfChargedHadrons_seeds_v[i0]), parts, iTaus);
139  }
140 }
141 
142 // create taus based on grid structure
144  const l1t::PFCandidateCollection& iParts,
145  std::unique_ptr<l1t::PFTauCollection>& outputTaus) {
146  l1t::PFCandidateCollection pfTauCands;
147  math::PtEtaPhiMLorentzVector lTot(0, 0, 0, 0);
148  math::PtEtaPhiMLorentzVector lCand(0, 0, 0, 0);
149  int lId = 0;
150  float z0 = 0;
151  float dxy = 0;
152  for (const auto& l1PFCand : iParts) {
153  if (reco::deltaR2(iCand, l1PFCand) > fConeSize_ * fConeSize_)
154  continue;
155  math::PtEtaPhiMLorentzVector pVec(l1PFCand.pt(), l1PFCand.eta(), l1PFCand.phi(), 0);
156  lTot += pVec;
157  if (reco::deltaR2(iCand, l1PFCand) < fTauSize_ * fTauSize_ &&
158  (l1PFCand.id() == l1t::PFCandidate::Electron || l1PFCand.id() == l1t::PFCandidate::ChargedHadron ||
159  l1PFCand.id() == l1t::PFCandidate::Photon)) {
160  lId++;
161  lCand += pVec;
162  if (z0 == 0 && l1PFCand.id() == l1t::PFCandidate::ChargedHadron) {
163  z0 = l1PFCand.z0();
164  dxy = l1PFCand.dxy();
165  }
166  }
167  pfTauCands.push_back(l1PFCand);
168  }
169  if (lTot.Pt() < fSeedPt_)
170  return;
171  std::sort(
172  pfTauCands.begin(), pfTauCands.end(), [](l1t::PFCandidate i, l1t::PFCandidate j) { return (i.pt() > j.pt()); });
173  float NN = fTauNNId_->compute(iCand, pfTauCands);
174  float* lNNVector = fTauNNId_->NNVectorVar();
175  math::PtEtaPhiMLorentzVector tempP4(lCand.Pt(), lCand.Eta(), lCand.Phi(), lCand.M() * lCand.M());
176  l1t::PFTau l1PFTau(tempP4, lNNVector, NN, 0, lId);
177  l1PFTau.setZ0(z0);
178  l1PFTau.setDxy(dxy);
179  outputTaus->push_back(l1PFTau);
180 }
182  // L1NNTauProducer
184  desc.add<std::string>("NNFileName", "L1Trigger/Phase2L1ParticleFlow/data/tau_3layer.pb");
185  desc.add<double>("tausize", 0.1);
186  desc.add<int>("maxtaus", 5);
187  desc.add<int>("nparticles", 10);
188  desc.add<double>("conesize", 0.4);
189  desc.add<double>("seedpt", 20);
190  desc.add<bool>("HW", true);
191  desc.add<bool>("emseed", true);
192  desc.add<bool>("debug", false);
193  desc.add<edm::InputTag>("L1PFObjects", edm::InputTag("L1PFProducer", "l1pfCandidates"));
194  descriptions.add("L1NNTauProducer", desc);
195 }
196 
199  std::unique_ptr<l1t::PFTauCollection>& iTaus) {
200  // Seed Cone Jet algorithm with ap_fixed types and hardware emulation
201  L1TauEmu::detaphi_t rCone2 =
203  unsigned lId = 0;
204 
205  input2_t p1_tot = 0;
206  input2_t p1x_tot = 0;
207  input2_t p1y_tot = 0;
208  input2_t p1z_tot = 0;
209 
210  input_t e1ta_1 = seed.eta();
211  input_t p1hi_1 = seed.phi();
212  L1TauEmu::pt_t pt = 0;
213  L1TauEmu::z0_t z0 = 0;
214  L1TauEmu::dxy_t dxy = 0;
215 
216  // Reconstruct the Tau Cone
217  for (unsigned i0 = 0; i0 < parts.size(); i0++) {
218  if (L1TauEmu::inCone(seed, (parts[i0]), rCone2)) {
220  parts[i0].id() == l1t::PFCandidate::Photon) {
221  lId++;
222  pt = pt + L1TauEmu::pt_t(parts[i0].pt());
223 
224  input2_t d1eta = input_t(parts[i0].eta()) - e1ta_1;
225  input2_t d1phi = input_t(parts[i0].phi()) - p1hi_1;
226  input2_t d1r2 = d1eta * d1eta + d1phi * d1phi;
227  input2_t tmppt = input_t(parts[i0].pt());
228  input2_t half = 0.5;
229  p1z_tot = p1z_tot + tmppt * (1 - d1r2 * half);
230  p1y_tot = p1y_tot + tmppt * d1phi;
231  p1x_tot = p1x_tot + tmppt * d1eta;
232  p1_tot = p1_tot + tmppt;
233 
234  if (z0 == 0 && parts[i0].id() == l1t::PFCandidate::ChargedHadron) {
235  z0 = parts[i0].hwZ0();
236  dxy = parts[i0].hwDxy();
237  }
238  }
239  }
240  }
241 
242  //Compute the mass
243  input2_t tmpmass1 = (p1_tot * p1_tot - p1x_tot * p1x_tot - p1y_tot * p1y_tot - p1z_tot * p1z_tot);
244  if (tmpmass1 < 0)
245  tmpmass1 = 0;
246  L1TauEmu::pt_t mass = l1ct::pt_t(tmpmass1);
247 
248  if (pt < fSeedPt_)
249  return;
250 
251  // Tau NN Inference
252  Tau_NN_Result NN_ouput = fTauNNIdHW_->compute(seed, parts);
253 
254  // Needed for making PFTau
255  input_t* lNNVector = fTauNNIdHW_->NNVectorVar();
256  float pNNVec[80];
257  for (unsigned i0 = 0; i0 < 80; i0++)
258  pNNVec[i0] = float(lNNVector[i0]);
259 
260  //Firmware Tau
261  l1ct::Tau l1ctTau;
262  l1ctTau.hwPt = l1ct::pt_t(pt * NN_ouput.nn_pt_correction); //l1gt is <16,11> and currently <16,14>
263  l1ctTau.hwEta = l1ct::Scales::makeGlbEta(seed.eta()); // seed.eta() and seed.phi() are in physical coordinates
264  l1ctTau.hwPhi = l1ct::Scales::makeGlbPhi(seed.phi());
265 
266  l1ctTau.hwSeedPt = seed.pt();
267  l1ctTau.hwSeedZ0 = seed.hwZ0();
268  l1ctTau.hwCharge = seed.charge();
269 
270  l1ctTau.hwType = l1ct::Tau::type_t(lId);
271  l1ctTau.hwRawId = ap_uint<10>(NN_ouput.nn_id * 1024); //NN Output is ap_fixed<16, 6> so need to cast.
272 
273  //Convert to GT format and pack to encodedTau of PFTau
274  l1gt::Tau l1gtTau = l1ctTau.toGT();
275  l1gt::PackedTau packed_Tau = l1gtTau.pack();
276 
277  //Make PFTau
278  //Save pt, eta and phi in gt scales
280  l1gt::Scales::floatEta(l1gtTau.v3.eta),
281  l1gt::Scales::floatPhi(l1gtTau.v3.phi),
282  float(mass));
283 
284  l1t::PFTau l1PFTau(tempP4, pNNVec, NN_ouput.nn_id, 0, lId);
285  l1PFTau.setZ0(float(z0) * 0.05); //L1TauEmu::z0_base);
286  l1PFTau.setDxy(float(dxy) * 0.05); //L1TauEmu::dxy_base);
287 
288  l1PFTau.set_encodedTau(packed_Tau);
289 
290  iTaus->push_back(l1PFTau);
291 }
292 
294  std::unique_ptr<l1t::PFTauCollection>& iTaus) {
295  // The fixed point algorithm emulation
296  using namespace L1TauEmu;
297  std::vector<l1t::PFCandidate> work;
298  work.resize(parts.size());
299  std::transform(parts.begin(), parts.end(), work.begin(), [](const l1t::PFCandidate& part) { return part; });
300  std::sort(work.begin(), work.end(), [](l1t::PFCandidate i, l1t::PFCandidate j) {
301  return (l1ct::pt_t(i.pt()) > l1ct::pt_t(j.pt()));
302  });
303 
304  std::vector<l1t::PFCandidate> seeds;
306  if (fEMSeed)
307  lSeed = l1t::PFCandidate::Photon;
308  std::copy_if(work.begin(), work.end(), std::back_inserter(seeds), [&](const l1t::PFCandidate& part) {
310  part.id() == lSeed) &&
312  });
313  // It would be nice to transform the inputs to the etaphi_base of the FW here, as in the line below
314  // However the phi may wrap around if the etaphi_base > 1, so don't do it...
315  //std::for_each(work.begin(), work.end(), [](l1t::PFCandidate& x){x.setP4(math::PtEtaPhiMLorentzVector(pt_t(x.pt()), etaphi_t(x.eta()*etaphi_base), etaphi_t(x.phi()*etaphi_base), x.mass()));});
317 
318  iTaus->reserve(fMaxTaus_);
319  while (!seeds.empty() && iTaus->size() < unsigned(fMaxTaus_)) {
320  // Take the first (highest pt) candidate as a seed
321  l1t::PFCandidate seed = seeds.at(0);
322  // Get the particles within a _coneSize of the seed
323  std::vector<l1t::PFCandidate> particlesInCone;
324  std::copy_if(work.begin(), work.end(), std::back_inserter(particlesInCone), [&](l1t::PFCandidate& part) {
325  return inCone(seed, part, rCone2);
326  });
327  makeTau_HW(seed, particlesInCone, iTaus);
328  // remove the clustered particles
329  work.erase(std::remove_if(
330  work.begin(), work.end(), [&](const l1t::PFCandidate& part) { return inCone(seed, part, rCone2); }),
331  work.end());
332 
333  seeds.erase(
334  std::remove_if(
335  seeds.begin(), seeds.end(), [&](const l1t::PFCandidate& part) { return inCone(seed, part, rCone2); }),
336  seeds.end());
337  }
338 }
339 
341 
void set_encodedTau(l1gt::PackedTau encodedTau)
Definition: PFTau.h:78
glbeta_t makeGlbEta(float eta)
Definition: datatypes.h:201
float floatPhi(phi_t phi)
Definition: gt_datatypes.h:48
float floatEta(eta_t eta)
Definition: gt_datatypes.h:47
static constexpr float track_trigger_eta_max
result_t nn_id
Definition: TauNNIdHW.h:19
std::string fullPath() const
Definition: FileInPath.cc:161
L1NNTauProducer(const edm::ParameterSet &, const tensorflow::SessionCache *)
static constexpr float etaphi_base
Definition: TauNNIdHW.h:27
std::unique_ptr< TauNNIdHW > fTauNNIdHW_
void setDxy(float dxy)
Definition: PFTau.h:52
std::vector< l1t::PFCandidate > PFCandidateCollection
Definition: PFCandidate.h:86
ap_fixed< 24, 12 > input2_t
Definition: defines.h:28
void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override
glbphi_t makeGlbPhi(float phi)
Definition: datatypes.h:204
delete x;
Definition: CaloConfig.h:22
ap_fixed< 12, 6 > detaphi_t
Definition: TauNNIdHW.h:30
void makeTau_HW(const l1t::PFCandidate &seed, l1t::PFCandidateCollection &parts, std::unique_ptr< l1t::PFTauCollection > &iTaus)
type_t hwType
Definition: taus.h:21
edm::EDGetTokenT< vector< l1t::PFCandidate > > fL1PFToken_
std::array< uint64_t, 2 > PackedTau
Definition: gt_datatypes.h:38
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:25
void addTau(const l1t::PFCandidate &iCand, const l1t::PFCandidateCollection &iParts, std::unique_ptr< PFTauCollection > &outputTaus)
std::unique_ptr< TauNNId > fTauNNId_
int iEvent
Definition: GenABIO.cc:224
constexpr Matriplex::idx_t NN
Definition: Matrix.h:43
ap_fixed< 16, 6 > input_t
Definition: defines.h:27
ap_uint< 2 > type_t
Definition: taus.h:11
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float floatPt(pt_t pt)
Definition: gt_datatypes.h:46
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
bool hwCharge
Definition: taus.h:20
glbphi_t hwPhi
Definition: taus.h:17
pt_t hwPt
Definition: taus.h:15
Definition: taus.h:10
z0_t hwSeedZ0
Definition: taus.h:19
~L1NNTauProducer() override
void setLogging(const std::string &level="3")
Definition: TensorFlow.cc:81
ap_ufixed< 14, 12, AP_TRN, AP_SAT > pt_t
Definition: datatypes.h:10
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
static std::unique_ptr< tensorflow::SessionCache > initializeGlobalCache(const edm::ParameterSet &)
part
Definition: HCALResponse.h:20
pt_t hwSeedPt
Definition: taus.h:18
l1gt::Tau toGT() const
Definition: taus.h:108
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void process_HW(const l1t::PFCandidateCollection &parts, std::unique_ptr< l1t::PFTauCollection > &iTaus)
glbeta_t hwEta
Definition: taus.h:16
HLT enums.
ap_ufixed< 16, 14 > pt_t
Definition: TauNNIdHW.h:28
def cache(function)
Definition: utilities.py:3
ap_int< 10 > z0_t
Definition: TauNNIdHW.h:34
const bool fEMSeed
void setZ0(float z0)
Definition: PFTau.h:51
ap_int< 8 > dxy_t
Definition: TauNNIdHW.h:33
PackedTau pack() const
Definition: gt_datatypes.h:218
bool inCone(l1t::PFCandidate seed, l1t::PFCandidate part, detaphi_t cone2)
Definition: TauNNIdHW.h:123
static void globalEndJob(const tensorflow::SessionCache *)
result_t nn_pt_correction
Definition: TauNNIdHW.h:18
rawid_t hwRawId
Definition: taus.h:22
void process_SW(const l1t::PFCandidateCollection &parts, std::unique_ptr< l1t::PFTauCollection > &iTaus)
def move(src, dest)
Definition: eostools.py:511
unsigned transform(const HcalDetId &id, unsigned transformCode)