CMS 3D CMS Logo

MuonRawDigiTranslator.cc
Go to the documentation of this file.
2 #include "TMath.h"
4 
6  uint32_t raw_data_spare,
7  uint32_t raw_data_00_31,
8  uint32_t raw_data_32_63,
9  int fed,
10  unsigned int fw,
11  int muInBx) {
12  // Need the hw charge to properly compute dPhi
13  mu.setHwCharge((raw_data_32_63 >> chargeShift_) & 0x1);
14 
15  // The position of the eta and phi coordinates in the RAW data changed between the 2016 run and the 2017 run.
16  // Eta and phi at the muon system are replaced by eta and phi at the vertex
17  // Eta and phi at the muon system are moved to spare bits
18  // In Run-3 we have displacement information.
19  // To make room for these data the raw eta value was moved to the second "spare" word which we will have to treat separately
20  // The uGMT (FED 1402) or uGT (FED 1404) FW versions are used to determine the era.
21  if ((fed == 1402 && fw < 0x4010000) || (fed == 1404 && fw < 0x10A6)) {
22  fillMuonCoordinates2016(mu, raw_data_00_31, raw_data_32_63);
23  } else if ((fed == 1402 && fw < 0x6000000) || (fed == 1404 && fw < 0x1120)) {
24  fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
25  } else if ((fed == 1402 && fw == 0x6000001) || (fed == 1404 && fw < 0x1130)) {
26  // We're unpacking data from the November MWGR where the raw eta values were shifted by one bit.
27  fillMuonQuantitiesRun3(mu, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, true);
28  } else {
29  fillMuonQuantitiesRun3(mu, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, false);
30  }
31 
32  // Fill pT, qual, iso, charge, index bits, coordinates at vtx
33  fillMuonStableQuantities(mu, raw_data_00_31, raw_data_32_63);
34 }
35 
37  uint32_t raw_data_00_31,
38  uint32_t raw_data_32_63,
39  unsigned int fw) {
40  // Need the hw charge to properly compute dPhi
41  mu.setHwCharge((raw_data_32_63 >> chargeShift_) & 0x1);
42 
43  if (fw < 0x4010000) {
44  fillMuonCoordinates2016(mu, raw_data_00_31, raw_data_32_63);
45  } else if (fw < 0x6000000) {
46  fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
47  } else {
48  fillIntermediateMuonQuantitiesRun3(mu, raw_data_00_31, raw_data_32_63);
49  }
50 
51  // Fill pT, qual, iso, charge, index bits, phys. coordinates at vtx & unconstrained pT
52  fillMuonStableQuantities(mu, raw_data_00_31, raw_data_32_63);
53 }
54 
55 void l1t::MuonRawDigiTranslator::fillMuonStableQuantities(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63) {
56  mu.setHwPt((raw_data_00_31 >> ptShift_) & ptMask_);
57  mu.setHwQual((raw_data_00_31 >> qualShift_) & qualMask_);
58  mu.setHwIso((raw_data_32_63 >> isoShift_) & isoMask_);
59  // charge is coded as -1^chargeBit
60  mu.setHwChargeValid((raw_data_32_63 >> chargeValidShift_) & 0x1);
61  mu.setTfMuonIndex((raw_data_32_63 >> tfMuonIndexShift_) & tfMuonIndexMask_);
62  if (mu.hwChargeValid()) {
63  mu.setCharge(1 - 2 * mu.hwCharge());
64  } else {
65  mu.setCharge(0);
66  }
67 
68  math::PtEtaPhiMLorentzVector vec{(mu.hwPt() - 1) * 0.5, mu.hwEta() * 0.010875, mu.hwPhi() * 0.010908, 0.0};
69  mu.setP4(vec);
70  // generate a muon at the vertex to extract the physical eta and phi coordinates
72  (mu.hwPt() - 1) * 0.5, mu.hwEtaAtVtx() * 0.010875, mu.hwPhiAtVtx() * 0.010908, 0.0};
73  Muon muAtVtx;
74  muAtVtx.setP4(vecAtVtx);
75  mu.setEtaAtVtx(muAtVtx.eta());
76  mu.setPhiAtVtx(muAtVtx.phi());
77 
78  int hwPtUnconstrained{mu.hwPtUnconstrained()};
79  mu.setPtUnconstrained(
80  hwPtUnconstrained == 0 ? 0 : (hwPtUnconstrained - 1)); // Don't want negative pT, unconstr. pT has LSB of 1 GeV.
81 }
82 
84  Muon& mu, uint32_t raw_data_spare, uint64_t dataword, int fed, unsigned int fw, int muInBx) {
85  fillMuon(
86  mu, raw_data_spare, (uint32_t)(dataword & 0xFFFFFFFF), (uint32_t)((dataword >> 32) & 0xFFFFFFFF), fed, fw, muInBx);
87 }
88 
89 void l1t::MuonRawDigiTranslator::fillMuonCoordinates2016(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63) {
90  // coordinates at the muon system are in 2016 where in 2017 eta and phi at the vertex are
91  mu.setHwEta(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
92  mu.setHwPhi((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
93 
94  // set the coordiantes at vertex to be the same as the coordinates at the muon system
95  mu.setHwEtaAtVtx(mu.hwEta());
96  mu.setHwPhiAtVtx(mu.hwPhi());
97  // deltas are 0
98  mu.setHwDEtaExtra(0);
99  mu.setHwDPhiExtra(0);
100 }
101 
103  uint32_t raw_data_00_31,
104  uint32_t raw_data_32_63) {
105  // coordinates at the muon system
106  mu.setHwEta(calcHwEta(raw_data_32_63, absEtaShift_, etaSignShift_));
107  mu.setHwPhi((raw_data_32_63 >> phiShift_) & phiMask_);
108 
109  // coordinates at the vertex
110  mu.setHwEtaAtVtx(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
111  mu.setHwPhiAtVtx((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
112  // deltas
113  mu.setHwDEtaExtra(mu.hwEtaAtVtx() - mu.hwEta());
114  int dPhi = mu.hwPhiAtVtx() - mu.hwPhi();
115  if (mu.hwCharge() == 1 && dPhi > 0) {
116  dPhi -= 576;
117  } else if (mu.hwCharge() == 0 && dPhi < 0) {
118  dPhi += 576;
119  }
120  mu.setHwDPhiExtra(dPhi);
121 }
122 
124  uint32_t raw_data_spare,
125  uint32_t raw_data_00_31,
126  uint32_t raw_data_32_63,
127  int muInBx,
128  bool wasSpecialMWGR /*= false*/) {
129  unsigned absEtaMu1Shift{absEtaMu1Shift_};
130  unsigned etaMu1SignShift{etaMu1SignShift_};
131  unsigned absEtaMu2Shift{absEtaMu2Shift_};
132  unsigned etaMu2SignShift{etaMu2SignShift_};
133 
134  // Adjust if we're unpacking data from the November 2020 MWGR.
135  if (wasSpecialMWGR) {
136  --absEtaMu1Shift;
137  --etaMu1SignShift;
138  --absEtaMu2Shift;
139  --etaMu2SignShift;
140  }
141  // coordinates at the muon system
142  // Where to find the raw eta depends on which muon we're looking at
143  if (muInBx == 1) {
144  mu.setHwEta(calcHwEta(raw_data_spare, absEtaMu1Shift, etaMu1SignShift));
145  } else if (muInBx == 2) {
146  mu.setHwEta(calcHwEta(raw_data_spare, absEtaMu2Shift, etaMu2SignShift));
147  } else {
148  edm::LogWarning("L1T") << "Received invalid muon id " << muInBx << ". Cannot fill eta value in the muon system.";
149  }
150  mu.setHwPhi((raw_data_32_63 >> phiShift_) & phiMask_);
151 
152  // coordinates at the vertex
153  mu.setHwEtaAtVtx(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
154  mu.setHwPhiAtVtx((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
155  // deltas
156  mu.setHwDEtaExtra(mu.hwEtaAtVtx() - mu.hwEta());
157  int dPhi = mu.hwPhiAtVtx() - mu.hwPhi();
158  if (mu.hwCharge() == 1 && dPhi > 0) {
159  dPhi -= 576;
160  } else if (mu.hwCharge() == 0 && dPhi < 0) {
161  dPhi += 576;
162  }
163  mu.setHwDPhiExtra(dPhi);
164 
165  // displacement information
166  mu.setHwDXY((raw_data_32_63 >> dxyShift_) & dxyMask_);
167  mu.setHwPtUnconstrained((raw_data_32_63 >> ptUnconstrainedShift_) & ptUnconstrainedMask_);
168 }
169 
171  uint32_t raw_data_00_31,
172  uint32_t raw_data_32_63) {
173  fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
174 
175  // displacement information
176  mu.setHwDXY((raw_data_32_63 >> dxyShift_) & dxyMask_);
177  mu.setHwPtUnconstrained((raw_data_00_31 >> ptUnconstrainedIntermedidateShift_) & ptUnconstrainedMask_);
178 }
179 
181  uint32_t& raw_data_spare,
182  uint32_t& raw_data_00_31,
183  uint32_t& raw_data_32_63,
184  const int fedID,
185  const int fwID,
186  const int muInBx) {
187  int abs_eta = mu.hwEta();
188  if (abs_eta < 0) {
189  abs_eta += (1 << (etaSignShift_ - absEtaShift_));
190  }
191  int abs_eta_at_vtx = mu.hwEtaAtVtx();
192  if (abs_eta_at_vtx < 0) {
193  abs_eta_at_vtx += (1 << (etaAtVtxSignShift_ - absEtaAtVtxShift_));
194  }
195  if ((fedID == 1402 && fwID < 0x4010000) || (fedID == 1404 && fwID < 0x10A6)) {
196  // For 2016 the non-extrapolated coordiantes were in the place that are now occupied by the extrapolated quantities.
197  raw_data_spare = 0;
198  raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
199  (abs_eta & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEta() < 0) << etaAtVtxSignShift_ |
200  (mu.hwPhi() & phiMask_) << phiAtVtxShift_;
201  raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
202  (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_;
203  } else if ((fedID == 1402 && fwID < 0x6000000) || (fedID == 1404 && fwID < 0x1120)) {
204  raw_data_spare = 0;
205  raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
206  (abs_eta_at_vtx & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEtaAtVtx() < 0) << etaAtVtxSignShift_ |
207  (mu.hwPhiAtVtx() & phiMask_) << phiAtVtxShift_;
208 
209  raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
210  (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_ |
211  (abs_eta & absEtaMask_) << absEtaShift_ | (mu.hwEta() < 0) << etaSignShift_ |
212  (mu.hwPhi() & phiMask_) << phiShift_;
213  } else if ((fedID == 1402 && fwID == 0x6000001) ||
214  (fedID == 1404 && fwID < 0x1130)) { // This allows us to unpack data taken in the November 2020 MWGR.
215  generatePackedMuonDataWordsRun3(
216  mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, true);
217  } else {
218  generatePackedMuonDataWordsRun3(
219  mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, false);
220  }
221 }
222 
224  const int abs_eta,
225  const int abs_eta_at_vtx,
226  uint32_t& raw_data_spare,
227  uint32_t& raw_data_00_31,
228  uint32_t& raw_data_32_63,
229  const int muInBx,
230  const bool wasSpecialMWGR /*= false*/) {
231  int absEtaShiftRun3{0}, etaSignShiftRun3{0};
232  if (muInBx == 1) {
233  absEtaShiftRun3 = absEtaMu1Shift_;
234  etaSignShiftRun3 = etaMu1SignShift_;
235  } else if (muInBx == 2) {
236  absEtaShiftRun3 = absEtaMu2Shift_;
237  etaSignShiftRun3 = etaMu2SignShift_;
238  }
239 
240  // Adjust if we're packing the November 2020 MWGR
241  if (wasSpecialMWGR && (muInBx == 1 || muInBx == 2)) {
242  --absEtaShiftRun3;
243  --etaSignShiftRun3;
244  }
245 
246  raw_data_spare = (abs_eta & absEtaMask_) << absEtaShiftRun3 | (mu.hwEta() < 0) << etaSignShiftRun3;
247  raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
248  (abs_eta_at_vtx & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEtaAtVtx() < 0) << etaAtVtxSignShift_ |
249  (mu.hwPhiAtVtx() & phiMask_) << phiAtVtxShift_;
250  raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
251  (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_ |
252  (mu.hwPhi() & phiMask_) << phiShift_ |
253  (mu.hwPtUnconstrained() & ptUnconstrainedMask_) << ptUnconstrainedShift_ |
254  (mu.hwDXY() & dxyMask_) << dxyShift_;
255 }
256 
258  const Muon& mu, uint32_t& raw_data_spare, uint64_t& dataword, int fedId, int fwId, int muInBx) {
259  uint32_t lsw;
260  uint32_t msw;
261 
262  generatePackedMuonDataWords(mu, raw_data_spare, lsw, msw, fedId, fwId, muInBx);
263  dataword = (((uint64_t)msw) << 32) + lsw;
264 }
265 
266 bool l1t::MuonRawDigiTranslator::showerFired(uint32_t shower_word, int fedId, unsigned int fwId) {
267  if ((fedId == 1402 && fwId >= 0x7000000) || (fedId == 1404 && fwId >= 0x00010f01)) {
268  return ((shower_word >> showerShift_) & 1) == 1;
269  }
270  return false;
271 }
272 
274  const int fedId,
275  const unsigned int fwId) {
276  std::array<uint32_t, 4> res{};
277  if ((fedId == 1402 && fwId >= 0x7000000) || (fedId == 1404 && fwId >= 0x00010f01)) {
278  res.at(0) = shower.isOneNominalInTime() ? (1 << showerShift_) : 0;
279  res.at(1) = shower.isOneTightInTime() ? (1 << showerShift_) : 0;
280  }
281  return res;
282 }
283 
285  const unsigned absEtaShift,
286  const unsigned etaSignShift) {
287  // eta is coded as two's complement
288  int abs_eta = (raw >> absEtaShift) & absEtaMask_;
289  if ((raw >> etaSignShift) & 0x1) {
290  return abs_eta - (1 << (etaSignShift - absEtaShift));
291  } else {
292  return abs_eta;
293  }
294 }
bool isOneTightInTime() const
Definition: MuonShower.h:75
static std::array< uint32_t, 4 > getPackedShowerDataWords(const MuonShower &shower, int fedId, unsigned int fwId)
static void fillMuonQuantitiesRun3(Muon &mu, uint32_t raw_data_spare, uint32_t raw_data_00_31, uint32_t raw_data_32_63, int muInBx, bool wasSpecialMWGR=false)
static int calcHwEta(const uint32_t &raw, unsigned absEtaShift, unsigned etaSignShift)
static void fillIntermediateMuon(Muon &mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63, unsigned int fw)
Definition: Electron.h:6
static void fillIntermediateMuonQuantitiesRun3(Muon &mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63)
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
Definition: LorentzVector.h:25
Definition: Muon.py:1
bool isOneNominalInTime() const
Definition: MuonShower.h:74
static constexpr unsigned chargeShift_
static void fillMuonStableQuantities(Muon &mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63)
static void generatePackedMuonDataWords(const Muon &mu, uint32_t &raw_data_spare, uint32_t &raw_data_00_31, uint32_t &raw_data_32_63, int fedId, int fwId, int muInBx)
unsigned long long uint64_t
Definition: Time.h:13
static void generate64bitDataWord(const Muon &mu, uint32_t &raw_data_spare, uint64_t &dataword, int fedId, int fwId, int muInBx)
static void fillMuonCoordinatesFrom2017(Muon &mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63)
static void fillMuon(Muon &mu, uint32_t raw_data_spare, uint32_t raw_data_00_31, uint32_t raw_data_32_63, int fed, unsigned int fw, int muInBx)
static void fillMuonCoordinates2016(Muon &mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63)
Log< level::Warning, false > LogWarning
static bool showerFired(uint32_t shower_word, int fedId, unsigned int fwId)
static void generatePackedMuonDataWordsRun3(const Muon &mu, int abs_eta, int abs_eta_at_vtx, uint32_t &raw_data_spare, uint32_t &raw_data_00_31, uint32_t &raw_data_32_63, int muInBx, bool wasSpecialMWGR=false)
double phi() const final
momentum azimuthal angle
void setP4(const LorentzVector &p4) final
set 4-momentum
double eta() const final
momentum pseudorapidity