CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Phase1L1TJetProducer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: L1CaloTrigger
4 // Class: Phase1L1TJetProducer
5 //
31 //
32 // Original Simone Bologna
33 // Created: Mon Jul 02 2018
34 // Modified 2020 Emyr Clement
35 //
36 
52 
53 #include "TH2F.h"
54 
55 #include <cmath>
56 
57 #include <algorithm>
58 constexpr int x_scroll_min = -4;
59 constexpr int x_scroll_max = 4;
60 constexpr int y_scroll_min = 0;
61 constexpr int y_scroll_max = 3;
62 
64 public:
65  explicit Phase1L1TJetProducer(const edm::ParameterSet&);
66  ~Phase1L1TJetProducer() override;
67 
68  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
69 
70 private:
71  void produce(edm::Event&, const edm::EventSetup&) override;
72 
74  std::vector<std::tuple<int, int>> findSeeds(float seedThreshold) const;
75 
76  // Calculates the pt sum of the bins around the seeds
77  // And applies some PU mitigation
78  // Warning - not used for some time, so user beware
79  std::vector<reco::CaloJet> buildJetsFromSeedsWithPUSubtraction(const std::vector<std::tuple<int, int>>& seeds,
80  bool killZeroPt) const;
81 
82  // Calculates the pt sum of the bins around the seeds
83  std::vector<reco::CaloJet> buildJetsFromSeeds(const std::vector<std::tuple<int, int>>& seeds) const;
84 
85  // Used by buildJetsFromSeedsWithPUSubtraction
86  // Implementation of pileup mitigation
87  // Warning - not used for some time, so user beware
88  void subtract9x9Pileup(reco::CaloJet& jet) const;
89 
91  float getTowerEnergy(int iEta, int iPhi) const;
92 
93  // Implementation of pt sum of bins around one seed
94  reco::CaloJet buildJetFromSeed(const std::tuple<int, int>& seed) const;
95 
96  // <3 handy method to fill the calogrid with whatever type
97  template <class Container>
98  void fillCaloGrid(TH2F& caloGrid, const Container& triggerPrimitives, const unsigned int regionIndex);
99 
100  // Digitise the eta and phi coordinates of input candidates
101  // This converts the quantities to integers to reduce precision
102  // And takes account of bin edge effects i.e. makes sure the
103  // candidate ends up in the correct (i.e. same behaviour as the firmware) bin of caloGrid_
104  std::pair<float, float> getCandidateDigiEtaPhi(const float eta,
105  const float phi,
106  const unsigned int regionIndex) const;
107 
108  // Sorts the input candidates into the PF regions they arrive in
109  // Truncates the inputs. Takes the first N candidates as they are provided, without any sorting (this may be needed in the future and/or provided in this way from emulation of layer 1)
110  template <class Handle>
111  std::vector<std::vector<reco::CandidatePtr>> prepareInputsIntoRegions(const Handle triggerPrimitives);
112 
113  // Converts phi and eta (PF) region indices to a single index
114  unsigned int getRegionIndex(const unsigned int phiRegion, const unsigned int etaRegion) const;
115  // From the single index, calculated by getRegionIndex, provides the lower eta and phi boundaries of the input (PF) region index
116  std::pair<double, double> regionEtaPhiLowEdges(const unsigned int regionIndex) const;
117  // From the single index, calculated by getRegionIndex, provides the upper eta and phi boundaries of the input (PF) region index
118  std::pair<double, double> regionEtaPhiUpEdges(const unsigned int regionIndex) const;
119 
120  // computes MET
121  // Takes grid used by jet finder and projects to 1D histogram of phi, bin contents are total pt in that phi bin
122  // the phi bin index is used to retrieve the sin-cos value from the LUT emulator
123  // the pt of the input is multiplied by that sin cos value to obtain px and py that is added to the total event px & py
124  // after all the inputs have been processed we compute the total pt of the event, and set that as MET
125  l1t::EtSum computeMET(const double etaCut, l1t::EtSum::EtSumType sumType) const;
126 
127  // Determine if this tower should be trimmed or not
128  // Used only when trimmedGrid_ option is set to true
129  // Trim means removing 3 towers in each corner of the square grid
130  // giving a cross shaped grid, which is a bit more circular in shape than a square
131  bool trimTower(const int etaIndex, const int phiIndex) const;
132 
134  // histogram containing our clustered inputs
135  std::unique_ptr<TH2F> caloGrid_;
136 
137  std::vector<double> etaBinning_;
138  size_t nBinsEta_;
139  unsigned int nBinsPhi_;
140  double phiLow_;
141  double phiUp_;
142  unsigned int jetIEtaSize_;
143  unsigned int jetIPhiSize_;
146  double ptlsb_;
147  double philsb_;
148  double etalsb_;
151  // Eta and phi edges of input PF regions
152  std::vector<double> etaRegionEdges_;
153  std::vector<double> phiRegionEdges_;
154  // Maximum number of candidates per input PF region
155  unsigned int maxInputsPerRegion_;
156  // LUT for sin and cos phi, to match that used in firmware
157  std::vector<double> sinPhi_;
158  std::vector<double> cosPhi_;
159  // input eta cut for met calculation
161  // input eta cut for metHF calculation
164 };
165 
167  : // getting configuration settings
168  inputCollectionTag_{
169  consumes<edm::View<reco::Candidate>>(iConfig.getParameter<edm::InputTag>("inputCollectionTag"))},
170  etaBinning_(iConfig.getParameter<std::vector<double>>("etaBinning")),
171  nBinsEta_(etaBinning_.size() - 1),
172  nBinsPhi_(iConfig.getParameter<unsigned int>("nBinsPhi")),
173  phiLow_(iConfig.getParameter<double>("phiLow")),
174  phiUp_(iConfig.getParameter<double>("phiUp")),
175  jetIEtaSize_(iConfig.getParameter<unsigned int>("jetIEtaSize")),
176  jetIPhiSize_(iConfig.getParameter<unsigned int>("jetIPhiSize")),
177  trimmedGrid_(iConfig.getParameter<bool>("trimmedGrid")),
178  seedPtThreshold_(iConfig.getParameter<double>("seedPtThreshold")),
179  ptlsb_(iConfig.getParameter<double>("ptlsb")),
180  philsb_(iConfig.getParameter<double>("philsb")),
181  etalsb_(iConfig.getParameter<double>("etalsb")),
182  puSubtraction_(iConfig.getParameter<bool>("puSubtraction")),
183  vetoZeroPt_(iConfig.getParameter<bool>("vetoZeroPt")),
184  etaRegionEdges_(iConfig.getParameter<std::vector<double>>("etaRegions")),
185  phiRegionEdges_(iConfig.getParameter<std::vector<double>>("phiRegions")),
186  maxInputsPerRegion_(iConfig.getParameter<unsigned int>("maxInputsPerRegion")),
187  sinPhi_(iConfig.getParameter<std::vector<double>>("sinPhi")),
188  cosPhi_(iConfig.getParameter<std::vector<double>>("cosPhi")),
189  metAbsEtaCut_(iConfig.getParameter<double>("metAbsEtaCut")),
190  metHFAbsEtaCut_(iConfig.getParameter<double>("metHFAbsEtaCut")),
191  outputCollectionName_(iConfig.getParameter<std::string>("outputCollectionName")) {
192  caloGrid_ =
193  std::make_unique<TH2F>("caloGrid", "Calorimeter grid", nBinsEta_, etaBinning_.data(), nBinsPhi_, phiLow_, phiUp_);
194  caloGrid_->GetXaxis()->SetTitle("#eta");
195  caloGrid_->GetYaxis()->SetTitle("#phi");
196  produces<std::vector<reco::CaloJet>>(outputCollectionName_).setBranchAlias(outputCollectionName_);
197  produces<std::vector<l1t::EtSum>>(outputCollectionName_ + "MET").setBranchAlias(outputCollectionName_ + "MET");
198 }
199 
201 
202 float Phase1L1TJetProducer::getTowerEnergy(int iEta, int iPhi) const {
203  // We return the pt of a certain bin in the calo grid, taking account of the phi periodicity when overflowing (e.g. phi > phiSize), and returning 0 for the eta out of bounds
204 
205  int nBinsEta = caloGrid_->GetNbinsX();
206  int nBinsPhi = caloGrid_->GetNbinsY();
207  while (iPhi < 1) {
208  iPhi += nBinsPhi;
209  }
210  while (iPhi > nBinsPhi) {
211  iPhi -= nBinsPhi;
212  }
213  if (iEta < 1) {
214  return 0;
215  }
216  if (iEta > nBinsEta) {
217  return 0;
218  }
219  return caloGrid_->GetBinContent(iEta, iPhi);
220 }
221 
223  edm::Handle<edm::View<reco::Candidate>> inputCollectionHandle;
224  iEvent.getByToken(inputCollectionTag_, inputCollectionHandle);
225 
226  // sort inputs into PF regions
227  std::vector<std::vector<reco::CandidatePtr>> inputsInRegions = prepareInputsIntoRegions<>(inputCollectionHandle);
228 
229  // histogramming the data
230  caloGrid_->Reset();
231  for (unsigned int iInputRegion = 0; iInputRegion < inputsInRegions.size(); ++iInputRegion) {
232  fillCaloGrid<>(*(caloGrid_), inputsInRegions[iInputRegion], iInputRegion);
233  }
234 
235  // find the seeds
236  const auto& seedsVector = findSeeds(seedPtThreshold_); // seedPtThreshold = 5
237  // build jets from the seeds
238  auto l1jetVector =
240 
241  // sort by pt
242  std::sort(l1jetVector.begin(), l1jetVector.end(), [](const reco::CaloJet& jet1, const reco::CaloJet& jet2) {
243  return jet1.pt() > jet2.pt();
244  });
245 
246  auto l1jetVectorPtr = std::make_unique<std::vector<reco::CaloJet>>(l1jetVector);
247  iEvent.put(std::move(l1jetVectorPtr), outputCollectionName_);
248 
249  // calculate METs
252  std::unique_ptr<std::vector<l1t::EtSum>> lSumVectorPtr(new std::vector<l1t::EtSum>(0));
253  lSumVectorPtr->push_back(lMET);
254  lSumVectorPtr->push_back(lMETHF);
255  iEvent.put(std::move(lSumVectorPtr), this->outputCollectionName_ + "MET");
256 
257  return;
258 }
259 
261  // these variables host the total pt in each sideband and the total pileup contribution
262  float topBandPt = 0;
263  float leftBandPt = 0;
264  float rightBandPt = 0;
265  float bottomBandPt = 0;
266  float pileUpEnergy;
267 
268  // hold the jet's x-y (and z, as I have to use it, even if 2D) location in the histo
269  int xCenter, yCenter, zCenter;
270  // Retrieving histo-coords for seed
271  caloGrid_->GetBinXYZ(caloGrid_->FindFixBin(jet.eta(), jet.phi()), xCenter, yCenter, zCenter);
272 
273  // Computing pileup
274  for (int x = x_scroll_min; x <= x_scroll_max; x++) {
275  for (int y = y_scroll_min; y < y_scroll_max; y++) {
276  // top band, I go up 5 squares to reach the bottom of the top band
277  // +x scrolls from left to right, +y scrolls up
278  topBandPt += getTowerEnergy(xCenter + x, yCenter + (5 + y));
279  // left band, I go left 5 squares (-5) to reach the bottom of the top band
280  // +x scrolls from bottom to top, +y scrolls left
281  leftBandPt += getTowerEnergy(xCenter - (5 + y), yCenter + x);
282  // right band, I go right 5 squares (+5) to reach the bottom of the top band
283  // +x scrolls from bottom to top, +y scrolls right
284  rightBandPt += getTowerEnergy(xCenter + (5 + y), yCenter + x);
285  // right band, I go right 5 squares (+5) to reach the bottom of the top band
286  // +x scrolls from bottom to top, +y scrolls right
287  bottomBandPt += getTowerEnergy(xCenter + x, yCenter - (5 + y));
288  }
289  }
290  // adding bands and removing the maximum band (equivalent to adding the three minimum bands)
291  pileUpEnergy = topBandPt + leftBandPt + rightBandPt + bottomBandPt -
292  std::max(topBandPt, std::max(leftBandPt, std::max(rightBandPt, bottomBandPt)));
293 
294  //preparing the new 4-momentum vector
296  // removing pu contribution
297  float ptAfterPUSubtraction = jet.pt() - pileUpEnergy;
298  ptVector.SetPt((ptAfterPUSubtraction > 0) ? ptAfterPUSubtraction : 0);
299  ptVector.SetEta(jet.eta());
300  ptVector.SetPhi(jet.phi());
301  //updating the jet
302  jet.setP4(ptVector);
303  jet.setPileup(pileUpEnergy);
304  return;
305 }
306 
307 std::vector<std::tuple<int, int>> Phase1L1TJetProducer::findSeeds(float seedThreshold) const {
308  int nBinsX = caloGrid_->GetNbinsX();
309  int nBinsY = caloGrid_->GetNbinsY();
310 
311  std::vector<std::tuple<int, int>> seeds;
312 
313  int etaHalfSize = (int)jetIEtaSize_ / 2;
314  int phiHalfSize = (int)jetIPhiSize_ / 2;
315 
316  // for each point of the grid check if it is a local maximum
317  // to do so I take a point, and look if is greater than the points around it (in the 9x9 neighborhood)
318  // to prevent mutual exclusion, I check greater or equal for points above and right to the one I am considering (including the top-left point)
319  // to prevent mutual exclusion, I check greater for points below and left to the one I am considering (including the bottom-right point)
320 
321  for (int iPhi = 1; iPhi <= nBinsY; iPhi++) {
322  for (int iEta = 1; iEta <= nBinsX; iEta++) {
323  float centralPt = caloGrid_->GetBinContent(iEta, iPhi);
324  if (centralPt < seedThreshold)
325  continue;
326  bool isLocalMaximum = true;
327 
328  // Scanning through the grid centered on the seed
329  for (int etaIndex = -etaHalfSize; etaIndex <= etaHalfSize; etaIndex++) {
330  for (int phiIndex = -phiHalfSize; phiIndex <= phiHalfSize; phiIndex++) {
331  if (trimmedGrid_) {
332  if (trimTower(etaIndex, phiIndex))
333  continue;
334  }
335 
336  if ((etaIndex == 0) && (phiIndex == 0))
337  continue;
338  if (phiIndex > 0) {
339  if (phiIndex > -etaIndex) {
340  isLocalMaximum = ((isLocalMaximum) && (centralPt > getTowerEnergy(iEta + etaIndex, iPhi + phiIndex)));
341  } else {
342  isLocalMaximum = ((isLocalMaximum) && (centralPt >= getTowerEnergy(iEta + etaIndex, iPhi + phiIndex)));
343  }
344  } else {
345  if (phiIndex >= -etaIndex) {
346  isLocalMaximum = ((isLocalMaximum) && (centralPt > getTowerEnergy(iEta + etaIndex, iPhi + phiIndex)));
347  } else {
348  isLocalMaximum = ((isLocalMaximum) && (centralPt >= getTowerEnergy(iEta + etaIndex, iPhi + phiIndex)));
349  }
350  }
351  }
352  }
353  if (isLocalMaximum) {
354  seeds.emplace_back(iEta, iPhi);
355  }
356  }
357  }
358 
359  return seeds;
360 }
361 
362 reco::CaloJet Phase1L1TJetProducer::buildJetFromSeed(const std::tuple<int, int>& seed) const {
363  int iEta = std::get<0>(seed);
364  int iPhi = std::get<1>(seed);
365 
366  int etaHalfSize = (int)jetIEtaSize_ / 2;
367  int phiHalfSize = (int)jetIPhiSize_ / 2;
368 
369  float ptSum = 0;
370  // Scanning through the grid centered on the seed
371  for (int etaIndex = -etaHalfSize; etaIndex <= etaHalfSize; etaIndex++) {
372  for (int phiIndex = -phiHalfSize; phiIndex <= phiHalfSize; phiIndex++) {
373  if (trimmedGrid_) {
374  if (trimTower(etaIndex, phiIndex))
375  continue;
376  }
377  ptSum += getTowerEnergy(iEta + etaIndex, iPhi + phiIndex);
378  }
379  }
380 
381  // Creating a jet with eta phi centered on the seed and momentum equal to the sum of the pt of the components
383  ptVector.SetPt(ptSum);
384  ptVector.SetEta(caloGrid_->GetXaxis()->GetBinCenter(iEta));
385  ptVector.SetPhi(caloGrid_->GetYaxis()->GetBinCenter(iPhi));
387  jet.setP4(ptVector);
388  return jet;
389 }
390 
392  const std::vector<std::tuple<int, int>>& seeds, bool killZeroPt) const {
393  // For each seed take a grid centered on the seed of the size specified by the user
394  // Sum the pf in the grid, that will be the pt of the l1t jet. Eta and phi of the jet is taken from the seed.
395  std::vector<reco::CaloJet> jets;
396  for (const auto& seed : seeds) {
398  subtract9x9Pileup(jet);
399  //killing jets with 0 pt
400  if ((vetoZeroPt_) && (jet.pt() <= 0))
401  continue;
402  jets.push_back(jet);
403  }
404  return jets;
405 }
406 
407 std::vector<reco::CaloJet> Phase1L1TJetProducer::buildJetsFromSeeds(
408  const std::vector<std::tuple<int, int>>& seeds) const {
409  // For each seed take a grid centered on the seed of the size specified by the user
410  // Sum the pf in the grid, that will be the pt of the l1t jet. Eta and phi of the jet is taken from the seed.
411  std::vector<reco::CaloJet> jets;
412  for (const auto& seed : seeds) {
414  jets.push_back(jet);
415  }
416  return jets;
417 }
418 
419 template <class Container>
421  const Container& triggerPrimitives,
422  const unsigned int regionIndex) {
423  //Filling the calo grid with the primitives
424  for (const auto& primitiveIterator : triggerPrimitives) {
425  // Get digitised (floating point with reduced precision) eta and phi
426  std::pair<float, float> digi_EtaPhi =
427  getCandidateDigiEtaPhi(primitiveIterator->eta(), primitiveIterator->phi(), regionIndex);
428 
429  caloGrid.Fill(static_cast<float>(digi_EtaPhi.first),
430  static_cast<float>(digi_EtaPhi.second),
431  static_cast<float>(primitiveIterator->pt()));
432  }
433 }
434 
435 std::pair<float, float> Phase1L1TJetProducer::getCandidateDigiEtaPhi(const float eta,
436  const float phi,
437  const unsigned int regionIndex) const {
438  std::pair<double, double> regionLowEdges = regionEtaPhiLowEdges(regionIndex);
439 
440  int digitisedEta = floor((eta - regionLowEdges.second) / etalsb_);
441  int digitisedPhi = floor((phi - regionLowEdges.first) / philsb_);
442 
443  // If eta or phi is on a bin edge
444  // Put in bin above, to match behaviour of HLS
445  // Unless it's on the last bin of this pf region
446  // Then it is placed in the last bin, not the overflow
447  TAxis* etaAxis = caloGrid_->GetXaxis();
448  std::pair<double, double> regionUpEdges = regionEtaPhiUpEdges(regionIndex);
449  int digiEtaEdgeLastBinUp = floor((regionUpEdges.second - regionLowEdges.second) / etalsb_);
450  // If the digi eta is outside the last bin of this pf region
451  // Set the digitised quantity so it would be in the last bin
452  // These cases could be avoided by sorting input candidates based on digitised eta/phi
453  if (digitisedEta >= digiEtaEdgeLastBinUp) {
454  digitisedEta = digiEtaEdgeLastBinUp - 1;
455  } else {
456  for (int i = 0; i < etaAxis->GetNbins(); ++i) {
457  if (etaAxis->GetBinUpEdge(i) < regionLowEdges.second)
458  continue;
459  int digiEdgeBinUp = floor((etaAxis->GetBinUpEdge(i) - regionLowEdges.second) / etalsb_);
460  if (digiEdgeBinUp == digitisedEta) {
461  digitisedEta += 1;
462  }
463  }
464  }
465 
466  // Similar for phi
467  TAxis* phiAxis = caloGrid_->GetYaxis();
468  int digiPhiEdgeLastBinUp = floor((regionUpEdges.first - regionLowEdges.first) / philsb_);
469  if (digitisedPhi >= digiPhiEdgeLastBinUp) {
470  digitisedPhi = digiPhiEdgeLastBinUp - 1;
471  } else {
472  for (int i = 0; i < phiAxis->GetNbins(); ++i) {
473  if (phiAxis->GetBinUpEdge(i) < regionLowEdges.first)
474  continue;
475  int digiEdgeBinUp = floor((phiAxis->GetBinUpEdge(i) - regionLowEdges.first) / philsb_);
476  if (digiEdgeBinUp == digitisedPhi) {
477  digitisedPhi += 1;
478  }
479  }
480  }
481 
482  // Convert digitised eta and phi back to floating point quantities with reduced precision
483  float floatDigitisedEta = (digitisedEta + 0.5) * etalsb_ + regionLowEdges.second;
484  float floatDigitisedPhi = (digitisedPhi + 0.5) * philsb_ + regionLowEdges.first;
485 
486  return std::pair<float, float>{floatDigitisedEta, floatDigitisedPhi};
487 }
488 
491  desc.add<edm::InputTag>("inputCollectionTag", edm::InputTag("l1pfCandidates", "Puppi"));
492  desc.add<std::vector<double>>("etaBinning");
493  desc.add<unsigned int>("nBinsPhi", 72);
494  desc.add<double>("phiLow", -M_PI);
495  desc.add<double>("phiUp", M_PI);
496  desc.add<unsigned int>("jetIEtaSize", 7);
497  desc.add<unsigned int>("jetIPhiSize", 7);
498  desc.add<bool>("trimmedGrid", false);
499  desc.add<double>("seedPtThreshold", 5);
500  desc.add<double>("ptlsb", 0.25), desc.add<double>("philsb", 0.0043633231), desc.add<double>("etalsb", 0.0043633231),
501  desc.add<bool>("puSubtraction", false);
502  desc.add<string>("outputCollectionName", "UncalibratedPhase1L1TJetFromPfCandidates");
503  desc.add<bool>("vetoZeroPt", true);
504  desc.add<std::vector<double>>("etaRegions");
505  desc.add<std::vector<double>>("phiRegions");
506  desc.add<unsigned int>("maxInputsPerRegion", 18);
507  desc.add<std::vector<double>>("sinPhi");
508  desc.add<std::vector<double>>("cosPhi");
509  desc.add<double>("metAbsEtaCut", 3);
510  desc.add<double>("metHFAbsEtaCut", 5);
511  descriptions.add("Phase1L1TJetProducer", desc);
512 }
513 
514 template <class Handle>
515 std::vector<std::vector<edm::Ptr<reco::Candidate>>> Phase1L1TJetProducer::prepareInputsIntoRegions(
516  const Handle triggerPrimitives) {
517  std::vector<std::vector<reco::CandidatePtr>> inputsInRegions{etaRegionEdges_.size() * (phiRegionEdges_.size() - 1)};
518 
519  for (unsigned int i = 0; i < triggerPrimitives->size(); ++i) {
520  reco::CandidatePtr tp(triggerPrimitives, i);
521 
522  if (tp->phi() < phiRegionEdges_.front() || tp->phi() >= phiRegionEdges_.back() ||
523  tp->eta() < etaRegionEdges_.front() || tp->eta() >= etaRegionEdges_.back())
524  continue;
525 
526  // Which phi region does this tp belong to
527  auto it_phi = phiRegionEdges_.begin();
528  it_phi = std::upper_bound(phiRegionEdges_.begin(), phiRegionEdges_.end(), tp->phi()) - 1;
529 
530  // Which eta region does this tp belong to
531  auto it_eta = etaRegionEdges_.begin();
532  it_eta = std::upper_bound(etaRegionEdges_.begin(), etaRegionEdges_.end(), tp->eta()) - 1;
533 
534  if (it_phi != phiRegionEdges_.end() && it_eta != etaRegionEdges_.end()) {
535  auto phiRegion = it_phi - phiRegionEdges_.begin();
536  auto etaRegion = it_eta - etaRegionEdges_.begin();
537  inputsInRegions[getRegionIndex(phiRegion, etaRegion)].emplace_back(tp);
538  }
539  }
540 
541  // Truncate number of inputs in each pf region
542  for (auto& inputs : inputsInRegions) {
543  if (inputs.size() > maxInputsPerRegion_) {
544  inputs.resize(maxInputsPerRegion_);
545  }
546  }
547 
548  return inputsInRegions;
549 }
550 
551 unsigned int Phase1L1TJetProducer::getRegionIndex(const unsigned int phiRegion, const unsigned int etaRegion) const {
552  return etaRegion * (phiRegionEdges_.size() - 1) + phiRegion;
553 }
554 
555 std::pair<double, double> Phase1L1TJetProducer::regionEtaPhiLowEdges(const unsigned int regionIndex) const {
556  unsigned int phiRegion = regionIndex % (phiRegionEdges_.size() - 1);
557  unsigned int etaRegion = (regionIndex - phiRegion) / (phiRegionEdges_.size() - 1);
558  return std::pair<double, double>{phiRegionEdges_.at(phiRegion), etaRegionEdges_.at(etaRegion)};
559 }
560 
561 std::pair<double, double> Phase1L1TJetProducer::regionEtaPhiUpEdges(const unsigned int regionIndex) const {
562  unsigned int phiRegion = regionIndex % (phiRegionEdges_.size() - 1);
563  unsigned int etaRegion = (regionIndex - phiRegion) / (phiRegionEdges_.size() - 1);
564  if (phiRegion == phiRegionEdges_.size() - 1) {
565  return std::pair<double, double>{phiRegionEdges_.at(phiRegion), etaRegionEdges_.at(etaRegion + 1)};
566  } else if (etaRegion == etaRegionEdges_.size() - 1) {
567  return std::pair<double, double>{phiRegionEdges_.at(phiRegion + 1), etaRegionEdges_.at(etaRegion)};
568  }
569 
570  return std::pair<double, double>{phiRegionEdges_.at(phiRegion + 1), etaRegionEdges_.at(etaRegion + 1)};
571 }
572 
574  const auto lowEtaBin = caloGrid_->GetXaxis()->FindBin(-1.0 * etaCut);
575  const auto highEtaBin = caloGrid_->GetXaxis()->FindBin(etaCut) - 1;
576  const auto phiProjection = caloGrid_->ProjectionY("temp", lowEtaBin, highEtaBin);
577 
578  // Use digitised quantities when summing to improve agreement with firmware
579  int totalDigiPx{0};
580  int totalDigiPy{0};
581 
582  for (int i = 1; i < phiProjection->GetNbinsX() + 1; ++i) {
583  double pt = phiProjection->GetBinContent(i);
584  totalDigiPx += trunc(floor(pt / ptlsb_) * cosPhi_[i - 1]);
585  totalDigiPy += trunc(floor(pt / ptlsb_) * sinPhi_[i - 1]);
586  }
587 
588  double lMET = floor(sqrt(totalDigiPx * totalDigiPx + totalDigiPy * totalDigiPy)) * ptlsb_;
589 
590  math::PtEtaPhiMLorentzVector lMETVector(lMET, 0, acos(totalDigiPx / (lMET / ptlsb_)), 0);
591  l1t::EtSum lMETSum(lMETVector, sumType, 0, 0, 0, 0);
592  return lMETSum;
593 }
594 
595 bool Phase1L1TJetProducer::trimTower(const int etaIndex, const int phiIndex) const {
596  int etaHalfSize = jetIEtaSize_ / 2;
597  int phiHalfSize = jetIPhiSize_ / 2;
598 
599  if (etaIndex == -etaHalfSize || etaIndex == etaHalfSize) {
600  if (phiIndex <= -phiHalfSize + 1 || phiIndex >= phiHalfSize - 1) {
601  return true;
602  }
603  } else if (etaIndex == -etaHalfSize + 1 || etaIndex == etaHalfSize - 1) {
604  if (phiIndex == -phiHalfSize || phiIndex == phiHalfSize) {
605  return true;
606  }
607  }
608 
609  return false;
610 }
unsigned int getRegionIndex(const unsigned int phiRegion, const unsigned int etaRegion) const
std::vector< double > phiRegionEdges_
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:133
std::vector< double > cosPhi_
Jets made from CaloTowers.
Definition: CaloJet.h:27
double pt() const final
transverse momentum
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
virtual void setPileup(float fEnergy)
Set pileup energy contribution as calculated by algorithm.
Definition: Jet.h:106
std::pair< double, double > regionEtaPhiUpEdges(const unsigned int regionIndex) const
void subtract9x9Pileup(reco::CaloJet &jet) const
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
bool trimTower(const int etaIndex, const int phiIndex) const
__host__ __device__ constexpr RandomIt upper_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
Phase1L1TJetProducer(const edm::ParameterSet &)
std::pair< float, float > getCandidateDigiEtaPhi(const float eta, const float phi, const unsigned int regionIndex) const
float getTowerEnergy(int iEta, int iPhi) const
Get the energy of a certain tower while correctly handling phi periodicity in case of overflow...
std::vector< std::vector< reco::CandidatePtr > > prepareInputsIntoRegions(const Handle triggerPrimitives)
std::vector< double > sinPhi_
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:25
constexpr int x_scroll_max
int iEvent
Definition: GenABIO.cc:224
std::pair< double, double > regionEtaPhiLowEdges(const unsigned int regionIndex) const
std::vector< double > etaBinning_
void produce(edm::Event &, const edm::EventSetup &) override
T sqrt(T t)
Definition: SSEVec.h:19
std::vector< reco::CaloJet > buildJetsFromSeeds(const std::vector< std::tuple< int, int >> &seeds) const
vector< PseudoJet > jets
def move
Definition: eostools.py:511
std::vector< reco::CaloJet > buildJetsFromSeedsWithPUSubtraction(const std::vector< std::tuple< int, int >> &seeds, bool killZeroPt) const
std::unique_ptr< TH2F > caloGrid_
void fillCaloGrid(TH2F &caloGrid, const Container &triggerPrimitives, const unsigned int regionIndex)
l1t::EtSum computeMET(const double etaCut, l1t::EtSum::EtSumType sumType) const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
constexpr int y_scroll_max
#define M_PI
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
constexpr int y_scroll_min
std::vector< double > etaRegionEdges_
reco::CaloJet buildJetFromSeed(const std::tuple< int, int > &seed) const
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
void add(std::string const &label, ParameterSetDescription const &psetDescription)
constexpr int x_scroll_min
std::vector< std::tuple< int, int > > findSeeds(float seedThreshold) const
Finds the seeds in the caloGrid, seeds are saved in a vector that contain the index in the TH2F of ea...
double phi() const final
momentum azimuthal angle
EtSumType
Definition: EtSum.h:22
edm::AssociationVector< reco::JetRefBaseProd, Values > Container
void setP4(const LorentzVector &p4) final
set 4-momentum
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38
double eta() const final
momentum pseudorapidity
edm::EDGetTokenT< edm::View< reco::Candidate > > inputCollectionTag_