CMS 3D CMS Logo

L1TrackerEtMissEmulatorProducer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: L1Trigger/L1TTrackMatch
4 // Class: L1TrackerEtMissEmulatorProducer
5 //
12 //
13 // Original Author: Christopher Brown
14 // Created: Fri, 19 Feb 2021
15 // Updated: Wed, 16 Jun 2021
16 //
17 //
18 
19 // system include files
20 #include <iomanip>
21 #include <memory>
22 #include <numeric>
23 #include <sstream>
24 // user include files
39 
40 using namespace l1t;
41 
43 public:
45  typedef std::vector<L1TTTrackType> L1TTTrackCollectionType;
47 
48  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
49 
52 
53 private:
54  virtual void beginJob();
55  void produce(edm::Event&, const edm::EventSetup&) override;
56  virtual void endJob();
57 
58  // ----------member data ---------------------------
59 
60  std::vector<l1tmetemu::cos_lut_fixed_t> cosLUT_; // Cos LUT array
61  std::vector<l1tmetemu::global_phi_t> phiQuadrants_;
62  std::vector<l1tmetemu::global_phi_t> phiShifts_;
63 
65  int debug_;
66  bool cordicDebug_ = false;
67 
69 
72 };
73 
74 // constructor//
76  : trackToken_(consumes<L1TTTrackRefCollectionType>(iConfig.getParameter<edm::InputTag>("L1TrackInputTag"))),
77  vtxAssocTrackToken_(
78  consumes<L1TTTrackRefCollectionType>(iConfig.getParameter<edm::InputTag>("L1TrackAssociatedInputTag"))) {
81 
82  // Get Emulator config parameters
83  cordicSteps_ = (int)iConfig.getParameter<int>("nCordicSteps");
84  debug_ = (int)iConfig.getParameter<int>("debug");
85 
86  // Name of output ED Product
87  L1MetCollectionName_ = (std::string)iConfig.getParameter<std::string>("L1MetCollectionName");
88 
89  if (debug_ == 5) {
90  cordicDebug_ = true;
91  }
92 
93  // To have same bin spacing between 0 and pi/2 as between original phi
94  // granularity
95  int cosLUTbins = std::floor(l1tmetemu::kMaxCosLUTPhi / TTTrack_TrackWord::stepPhi0);
96 
97  // Compute LUTs
98  cosLUT_ = l1tmetemu::generateCosLUT(cosLUTbins);
99 
100  // Print LUTs
101  if (debug_ == 1) {
102  l1tmetemu::printLUT(phiQuadrants_, "L1TrackerEtMissEmulatorProducer", "phiQuadrants_");
103  l1tmetemu::printLUT(phiShifts_, "L1TrackerEtMissEmulatorProducer", "phiShifts_");
104  l1tmetemu::printLUT(cosLUT_, "L1TrackerEtMissEmulatorProducer", "cosLUT_");
105  }
106 
107  produces<std::vector<EtSum>>(L1MetCollectionName_);
108 }
109 
111 
113  using namespace edm;
114 
115  std::unique_ptr<std::vector<l1t::EtSum>> METCollection(new std::vector<l1t::EtSum>(0));
116 
118  iEvent.getByToken(trackToken_, L1TTTrackHandle);
119 
120  edm::Handle<L1TTTrackRefCollectionType> L1TTTrackAssociatedHandle;
121  iEvent.getByToken(vtxAssocTrackToken_, L1TTTrackAssociatedHandle);
122 
123  // Initialize cordic class
125 
126  if (!L1TTTrackHandle.isValid()) {
127  LogError("L1TrackerEtMissEmulatorProducer") << "\nWarning: L1TTTrackCollection not found in the event. Exit\n";
128  return;
129  }
130 
131  if (!L1TTTrackAssociatedHandle.isValid()) {
132  LogError("L1TrackerEtMissEmulatorProducer")
133  << "\nWarning: L1TTTrackAssociatedCollection not found in the event. Exit\n";
134  return;
135  }
136 
137  // Initialize sector sums, need 0 initialization in case a sector has no
138  // tracks
139  l1tmetemu::Et_t sumPx[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
140  l1tmetemu::Et_t sumPy[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
141  int link_totals[l1tmetemu::kNSector * 2] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
142  int sector_totals[l1tmetemu::kNSector] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
143 
144  // Track counters
145  int num_assoc_tracks{0};
146 
147  for (const auto& track : *L1TTTrackHandle) {
148  if (std::find(L1TTTrackAssociatedHandle->begin(), L1TTTrackAssociatedHandle->end(), track) !=
149  L1TTTrackAssociatedHandle->end()) {
150  bool EtaSector = (track->getTanlWord() & (1 << (TTTrack_TrackWord::TrackBitWidths::kTanlSize - 1)));
151 
152  ap_uint<TTTrack_TrackWord::TrackBitWidths::kRinvSize - 1> ptEmulationBits = track->getTrackWord()(
153  TTTrack_TrackWord::TrackBitLocations::kRinvMSB - 1, TTTrack_TrackWord::TrackBitLocations::kRinvLSB);
154  ap_ufixed<TTTrack_TrackWord::TrackBitWidths::kRinvSize - 1, l1tmetemu::kPtMagSize> ptEmulation;
155  ptEmulation.V = ptEmulationBits.range();
156 
157  l1tmetemu::global_phi_t globalPhi =
158  l1tmetemu::localToGlobalPhi(track->getPhiWord(), phiShifts_[track->phiSector()]);
159 
160  num_assoc_tracks++;
161  if (debug_ == 7) {
162  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
163  << "Track to Vertex ID: " << num_assoc_tracks << "\n"
164  << "Phi Sector: " << track->phiSector() << " pT: " << track->getRinvWord()
165  << " Phi: " << track->getPhiWord() << " TanL: " << track->getTanlWord() << " Z0: " << track->getZ0Word()
166  << " Chi2rphi: " << track->getChi2RPhiWord() << " Chi2rz: " << track->getChi2RZWord()
167  << " bendChi2: " << track->getBendChi2Word() << " Emu pT " << ptEmulation.to_double() << "\n"
168  << "--------------------------------------------------------------\n";
169  }
170 
171  if (debug_ == 2) {
172  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
173  << "========================Phi debug=================================\n"
174  << "Emu pT: " << ptEmulation.to_double() << " float pT: " << track->momentum().perp() << "\n"
175  << "Int Phi: " << globalPhi << " Float Phi: " << track->phi() << " Float Cos(Phi): " << cos(track->phi())
176  << " Float Sin(Phi): " << sin(track->phi())
177  << " Float Px: " << track->momentum().perp() * cos(track->phi())
178  << " Float Py: " << track->momentum().perp() * sin(track->phi()) << "\n";
179  }
180 
181  l1tmetemu::Et_t temppx = 0;
182  l1tmetemu::Et_t temppy = 0;
183 
184  // Split tracks in phi quadrants and access cosLUT_, backwards iteration
185  // through cosLUT_ gives sin Sum sector Et -ve when cos or sin phi are -ve
186  sector_totals[track->phiSector()] += 1;
187  if (globalPhi >= phiQuadrants_[0] && globalPhi < phiQuadrants_[1]) {
188  temppx = ((l1tmetemu::Et_t)ptEmulation * cosLUT_[globalPhi]);
189  temppy = ((l1tmetemu::Et_t)ptEmulation * cosLUT_[phiQuadrants_[1] - 1 - globalPhi]);
190 
191  if (debug_ == 2) {
192  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
193  << "Sector: " << track->phiSector() << " Quadrant: " << 1 << "\n"
194  << "Emu Phi: " << globalPhi << " Emu Cos(Phi): " << cosLUT_[globalPhi]
195  << " Emu Sin(Phi): " << cosLUT_[phiQuadrants_[1] - 1 - globalPhi] << "\n";
196  }
197  } else if (globalPhi >= phiQuadrants_[1] && globalPhi < phiQuadrants_[2]) {
198  temppx = -((l1tmetemu::Et_t)ptEmulation * cosLUT_[phiQuadrants_[2] - 1 - globalPhi]);
199  temppy = ((l1tmetemu::Et_t)ptEmulation * cosLUT_[globalPhi - phiQuadrants_[1]]);
200 
201  if (debug_ == 2) {
202  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
203  << "Sector: " << track->phiSector() << " Quadrant: " << 2 << "\n"
204  << "Emu Phi: " << globalPhi << " Emu Cos(Phi): -" << cosLUT_[phiQuadrants_[2] - 1 - globalPhi]
205  << " Emu Sin(Phi): " << cosLUT_[globalPhi - phiQuadrants_[1]] << "\n";
206  }
207  } else if (globalPhi >= phiQuadrants_[2] && globalPhi < phiQuadrants_[3]) {
208  temppx = -((l1tmetemu::Et_t)ptEmulation * cosLUT_[globalPhi - phiQuadrants_[2]]);
209  temppy = -((l1tmetemu::Et_t)ptEmulation * cosLUT_[phiQuadrants_[3] - 1 - globalPhi]);
210 
211  if (debug_ == 2) {
212  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
213  << "Sector: " << track->phiSector() << " Quadrant: " << 3 << "\n"
214  << "Emu Phi: " << globalPhi << " Emu Cos(Phi): -" << cosLUT_[globalPhi - phiQuadrants_[2]]
215  << " Emu Sin(Phi): -" << cosLUT_[phiQuadrants_[3] - 1 - globalPhi] << "\n";
216  }
217 
218  } else if (globalPhi >= phiQuadrants_[3] && globalPhi < phiQuadrants_[4]) {
219  temppx = ((l1tmetemu::Et_t)ptEmulation * cosLUT_[phiQuadrants_[4] - 1 - globalPhi]);
220  temppy = -((l1tmetemu::Et_t)ptEmulation * cosLUT_[globalPhi - phiQuadrants_[3]]);
221 
222  if (debug_ == 2) {
223  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
224  << "Sector: " << track->phiSector() << " Quadrant: " << 4 << "\n"
225  << " Emu Phi: " << globalPhi << " Emu Cos(Phi): " << cosLUT_[phiQuadrants_[4] - 1 - globalPhi]
226  << " Emu Sin(Phi): -" << cosLUT_[globalPhi - phiQuadrants_[3]] << "\n";
227  }
228  } else {
229  temppx = 0;
230  temppy = 0;
231  }
232 
233  int link_number = (track->phiSector() * 2) + ((EtaSector) ? 0 : 1);
234  link_totals[link_number] += 1;
235  sumPx[link_number] += temppx;
236  sumPy[link_number] += temppy;
237 
238  if (debug_ == 4) {
239  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
240  << std::setprecision(8) << "Sector: " << track->phiSector() << " Eta sector: " << EtaSector << "\n"
241  << "Track Ref Pt: " << track->momentum().perp() << " Track Ref Px: " << track->momentum().x()
242  << " Track Ref Py: " << track->momentum().y() << "\n"
243  << "Track Pt: " << ptEmulation << " Track phi: " << globalPhi << " Track Px: " << temppx
244  << " Track Py: " << temppy << "\n"
245  << "Sector Sum Px: " << sumPx[link_number] << " Sector Sum Py: " << sumPy[link_number] << "\n";
246  }
247  }
248  } // end loop over tracks
249 
250  l1tmetemu::Et_t GlobalPx = 0;
251  l1tmetemu::Et_t GlobalPy = 0;
252 
253  // Global Et sum as floats to emulate rounding in HW
254  for (unsigned int i = 0; i < l1tmetemu::kNSector * 2; i++) {
255  GlobalPx += sumPx[i];
256  GlobalPy += sumPy[i];
257  }
258 
259  // Perform cordic sqrt, take x,y and converts to polar coordinate r,phi where
260  // r=sqrt(x**2+y**2) and phi = atan(y/x)
261  l1tmetemu::EtMiss EtMiss = cordicSqrt.toPolar(-GlobalPx, -GlobalPy);
262 
263  if (debug_ == 4 || debug_ == 6) {
264  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer") << "====Sector Pt====\n";
265 
266  for (unsigned int i = 0; i < l1tmetemu::kNSector * 2; i++) {
267  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
268  << "Sector " << i << "\n"
269  << "Px: " << sumPx[i] << " | Py: " << sumPy[i] << " | Link Totals: " << link_totals[i]
270  << " | Sector Totals: " << sector_totals[(int)(i / 2)] << "\n";
271  }
272 
273  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
274  << "====Global Pt====\n"
275  << "Global Px: " << GlobalPx << "| Global Py: " << GlobalPy << "\n";
276 
277  edm::LogVerbatim("L1TrackerEtMissEmulatorProducer")
278  << "====MET===\n"
279  << "MET word Et: " << EtMiss.Et.range() * l1tmetemu::kStepMETwordEt << "| MET word phi: " << EtMiss.Phi << "\n"
280  << "MET: " << EtMiss.Et.to_double() << "| MET phi: " << EtMiss.Phi.to_double() * l1tmetemu::kStepMETwordPhi
281  << "\n"
282  << "Word MET: " << EtMiss.Et.to_string(2) << " | Word MET phi: " << EtMiss.Phi.to_string(2) << "\n"
283  << "# Tracks Associated to Vertex: " << num_assoc_tracks << "\n"
284  << "========================================================\n";
285  }
286 
287  math::XYZTLorentzVector missingEt(-GlobalPx, -GlobalPy, 0, EtMiss.Et);
288  EtSum L1EtSum(missingEt, EtSum::EtSumType::kMissingEt, EtMiss.Et.range(), 0, EtMiss.Phi, num_assoc_tracks);
289 
290  METCollection->push_back(L1EtSum);
291 
293 } // end producer
294 
296 
298 
299 // ------------ method fills 'descriptions' with the allowed parameters for the module ------------
301  //The following says we do not know what parameters are allowed so do no validation
302  // Please change this to state exactly what you do use, even if it is no parameters
304  desc.setUnknown();
305  descriptions.addDefault(desc);
306 }
307 
308 // define this as a plug-in
Log< level::Info, true > LogVerbatim
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
ap_fixed< kMETSize+kEtExtra, kMETMagSize+kEtExtra, AP_RND_CONV, AP_SAT > Et_t
TTTrack< Ref_Phase2TrackerDigi_ > L1TTTrackType
ap_int< TTTrack_TrackWord::TrackBitWidths::kPhiSize+kGlobalPhiExtra > global_phi_t
std::vector< l1tmetemu::global_phi_t > phiQuadrants_
void printLUT(std::vector< T > lut, std::string module="", std::string name="")
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
delete x;
Definition: CaloConfig.h:22
EtMiss cordicSqrt(Et_t x, Et_t y, int cordicSteps, std::vector< l1tmhtemu::MHTphi_t > atanLUT, std::vector< Et_t > magNormalisationLUT)
global_phi_t localToGlobalPhi(TTTrack_TrackWord::phi_t local_phi, global_phi_t sector_shift)
const double kStepMETwordEt
Log< level::Error, false > LogError
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
const unsigned int kNQuadrants
std::vector< reco::MET > METCollection
collection of MET objects
Definition: METCollection.h:22
void beginJob()
Definition: Breakpoints.cc:14
const unsigned int kNSector
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
int iEvent
Definition: GenABIO.cc:224
void addDefault(ParameterSetDescription const &psetDescription)
void produce(edm::Event &, const edm::EventSetup &) override
const double kMaxCosLUTPhi
const edm::EDGetTokenT< L1TTTrackRefCollectionType > vtxAssocTrackToken_
L1TrackerEtMissEmulatorProducer(const edm::ParameterSet &)
const double kStepMETwordPhi
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
const edm::EDGetTokenT< L1TTTrackRefCollectionType > trackToken_
Definition: Cordic.h:7
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
Collection of MET.
std::vector< l1tmetemu::global_phi_t > phiShifts_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Class to store the L1 Track Trigger tracks.
Definition: TTTrack.h:29
static constexpr double stepPhi0
std::vector< global_phi_t > generatePhiSliceLUT(unsigned int N)
std::vector< l1tmetemu::cos_lut_fixed_t > cosLUT_
const unsigned int kPtMagSize
bool isValid() const
Definition: HandleBase.h:70
std::vector< cos_lut_fixed_t > generateCosLUT(unsigned int size)
HLT enums.
edm::RefVector< L1TTTrackCollectionType > L1TTTrackRefCollectionType
std::vector< L1TTTrackType > L1TTTrackCollectionType
def move(src, dest)
Definition: eostools.py:511