Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-30 05:19:59

0001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0002 #include "TMath.h"
0003 #include "L1Trigger/L1TMuon/interface/MuonRawDigiTranslator.h"
0004 
0005 void l1t::MuonRawDigiTranslator::fillMuon(
0006     Muon& mu, uint32_t raw_data_spare, uint32_t raw_data_00_31, uint32_t raw_data_32_63, int fed, int fw, int muInBx) {
0007   // Need the hw charge to properly compute dPhi
0008   mu.setHwCharge((raw_data_32_63 >> chargeShift_) & 0x1);
0009 
0010   // The position of the eta and phi coordinates in the RAW data changed between the 2016 run and the 2017 run.
0011   // Eta and phi at the muon system are replaced by eta and phi at the vertex
0012   // Eta and phi at the muon system are moved to spare bits
0013   // In Run-3 we have displacement information.
0014   // To make room for these data the raw eta value was moved to the second "spare" word which we will have to treat separately
0015   // The uGMT (FED 1402) or uGT (FED 1404) FW versions are used to determine the era.
0016   if ((fed == kUgmtFedId && fw < kUgmtFwVersionUntil2016) || (fed == kUgtFedId && fw < kUgtFwVersionUntil2016)) {
0017     fillMuonCoordinates2016(mu, raw_data_00_31, raw_data_32_63);
0018   } else if ((fed == kUgmtFedId && fw < kUgmtFwVersionUntil2017) || (fed == kUgtFedId && fw < kUgtFwVersionUntil2017)) {
0019     fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
0020   } else if ((fed == kUgmtFedId && fw == kUgmtFwVersionRun3Start) ||
0021              (fed == kUgtFedId && fw < kUgtFwVersionUntilRun3Start)) {
0022     // We're unpacking data from the November MWGR where the raw eta values were shifted by one bit.
0023     fillMuonQuantitiesRun3(mu, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, true);
0024   } else {
0025     fillMuonQuantitiesRun3(mu, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, false);
0026   }
0027 
0028   // Fill pT, qual, iso, charge, index bits, coordinates at vtx
0029   fillMuonStableQuantities(mu, raw_data_00_31, raw_data_32_63);
0030 }
0031 
0032 void l1t::MuonRawDigiTranslator::fillIntermediateMuon(Muon& mu,
0033                                                       uint32_t raw_data_00_31,
0034                                                       uint32_t raw_data_32_63,
0035                                                       int fw) {
0036   // Need the hw charge to properly compute dPhi
0037   mu.setHwCharge((raw_data_32_63 >> chargeShift_) & 0x1);
0038 
0039   if (fw < kUgmtFwVersionUntil2016) {
0040     fillMuonCoordinates2016(mu, raw_data_00_31, raw_data_32_63);
0041   } else if (fw < kUgmtFwVersionUntil2017) {
0042     fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
0043   } else {
0044     fillIntermediateMuonQuantitiesRun3(mu, raw_data_00_31, raw_data_32_63);
0045   }
0046 
0047   // Fill pT, qual, iso, charge, index bits,  phys. coordinates at vtx & unconstrained pT
0048   fillMuonStableQuantities(mu, raw_data_00_31, raw_data_32_63);
0049 }
0050 
0051 void l1t::MuonRawDigiTranslator::fillMuonStableQuantities(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63) {
0052   mu.setHwPt((raw_data_00_31 >> ptShift_) & ptMask_);
0053   mu.setHwQual((raw_data_00_31 >> qualShift_) & qualMask_);
0054   mu.setHwIso((raw_data_32_63 >> isoShift_) & isoMask_);
0055   // charge is coded as -1^chargeBit
0056   mu.setHwChargeValid((raw_data_32_63 >> chargeValidShift_) & 0x1);
0057   mu.setTfMuonIndex((raw_data_32_63 >> tfMuonIndexShift_) & tfMuonIndexMask_);
0058   if (mu.hwChargeValid()) {
0059     mu.setCharge(1 - 2 * mu.hwCharge());
0060   } else {
0061     mu.setCharge(0);
0062   }
0063 
0064   math::PtEtaPhiMLorentzVector vec{(mu.hwPt() - 1) * 0.5, mu.hwEta() * 0.010875, mu.hwPhi() * 0.010908, 0.0};
0065   mu.setP4(vec);
0066   // generate a muon at the vertex to extract the physical eta and phi coordinates
0067   math::PtEtaPhiMLorentzVector vecAtVtx{
0068       (mu.hwPt() - 1) * 0.5, mu.hwEtaAtVtx() * 0.010875, mu.hwPhiAtVtx() * 0.010908, 0.0};
0069   Muon muAtVtx;
0070   muAtVtx.setP4(vecAtVtx);
0071   mu.setEtaAtVtx(muAtVtx.eta());
0072   mu.setPhiAtVtx(muAtVtx.phi());
0073 
0074   int hwPtUnconstrained{mu.hwPtUnconstrained()};
0075   mu.setPtUnconstrained(
0076       hwPtUnconstrained == 0 ? 0 : (hwPtUnconstrained - 1));  // Don't want negative pT, unconstr. pT has LSB of 1 GeV.
0077 }
0078 
0079 void l1t::MuonRawDigiTranslator::fillMuon(
0080     Muon& mu, uint32_t raw_data_spare, uint64_t dataword, int fed, int fw, int muInBx) {
0081   fillMuon(
0082       mu, raw_data_spare, (uint32_t)(dataword & 0xFFFFFFFF), (uint32_t)((dataword >> 32) & 0xFFFFFFFF), fed, fw, muInBx);
0083 }
0084 
0085 void l1t::MuonRawDigiTranslator::fillMuonCoordinates2016(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63) {
0086   // coordinates at the muon system are in 2016 where in 2017 eta and phi at the vertex are
0087   mu.setHwEta(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
0088   mu.setHwPhi((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
0089 
0090   // set the coordiantes at vertex to be the same as the coordinates at the muon system
0091   mu.setHwEtaAtVtx(mu.hwEta());
0092   mu.setHwPhiAtVtx(mu.hwPhi());
0093   // deltas are 0
0094   mu.setHwDEtaExtra(0);
0095   mu.setHwDPhiExtra(0);
0096 }
0097 
0098 void l1t::MuonRawDigiTranslator::fillMuonCoordinatesFrom2017(Muon& mu,
0099                                                              uint32_t raw_data_00_31,
0100                                                              uint32_t raw_data_32_63) {
0101   // coordinates at the muon system
0102   mu.setHwEta(calcHwEta(raw_data_32_63, absEtaShift_, etaSignShift_));
0103   mu.setHwPhi((raw_data_32_63 >> phiShift_) & phiMask_);
0104 
0105   // coordinates at the vertex
0106   mu.setHwEtaAtVtx(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
0107   mu.setHwPhiAtVtx((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
0108   // deltas
0109   mu.setHwDEtaExtra(mu.hwEtaAtVtx() - mu.hwEta());
0110   int dPhi = mu.hwPhiAtVtx() - mu.hwPhi();
0111   if (mu.hwCharge() == 1 && dPhi > 0) {
0112     dPhi -= 576;
0113   } else if (mu.hwCharge() == 0 && dPhi < 0) {
0114     dPhi += 576;
0115   }
0116   mu.setHwDPhiExtra(dPhi);
0117 }
0118 
0119 void l1t::MuonRawDigiTranslator::fillMuonQuantitiesRun3(Muon& mu,
0120                                                         uint32_t raw_data_spare,
0121                                                         uint32_t raw_data_00_31,
0122                                                         uint32_t raw_data_32_63,
0123                                                         int muInBx,
0124                                                         bool wasSpecialMWGR /*= false*/) {
0125   unsigned absEtaMu1Shift{absEtaMu1Shift_};
0126   unsigned etaMu1SignShift{etaMu1SignShift_};
0127   unsigned absEtaMu2Shift{absEtaMu2Shift_};
0128   unsigned etaMu2SignShift{etaMu2SignShift_};
0129 
0130   // Adjust if we're unpacking data from the November 2020 MWGR.
0131   if (wasSpecialMWGR) {
0132     --absEtaMu1Shift;
0133     --etaMu1SignShift;
0134     --absEtaMu2Shift;
0135     --etaMu2SignShift;
0136   }
0137   // coordinates at the muon system
0138   // Where to find the raw eta depends on which muon we're looking at
0139   if (muInBx == 1) {
0140     mu.setHwEta(calcHwEta(raw_data_spare, absEtaMu1Shift, etaMu1SignShift));
0141   } else if (muInBx == 2) {
0142     mu.setHwEta(calcHwEta(raw_data_spare, absEtaMu2Shift, etaMu2SignShift));
0143   } else {
0144     edm::LogWarning("L1T") << "Received invalid muon id " << muInBx << ". Cannot fill eta value in the muon system.";
0145   }
0146   mu.setHwPhi((raw_data_32_63 >> phiShift_) & phiMask_);
0147 
0148   // coordinates at the vertex
0149   mu.setHwEtaAtVtx(calcHwEta(raw_data_00_31, absEtaAtVtxShift_, etaAtVtxSignShift_));
0150   mu.setHwPhiAtVtx((raw_data_00_31 >> phiAtVtxShift_) & phiMask_);
0151   // deltas
0152   mu.setHwDEtaExtra(mu.hwEtaAtVtx() - mu.hwEta());
0153   int dPhi = mu.hwPhiAtVtx() - mu.hwPhi();
0154   if (mu.hwCharge() == 1 && dPhi > 0) {
0155     dPhi -= 576;
0156   } else if (mu.hwCharge() == 0 && dPhi < 0) {
0157     dPhi += 576;
0158   }
0159   mu.setHwDPhiExtra(dPhi);
0160 
0161   // displacement information
0162   mu.setHwDXY((raw_data_32_63 >> dxyShift_) & dxyMask_);
0163   mu.setHwPtUnconstrained((raw_data_32_63 >> ptUnconstrainedShift_) & ptUnconstrainedMask_);
0164 }
0165 
0166 void l1t::MuonRawDigiTranslator::fillIntermediateMuonQuantitiesRun3(Muon& mu,
0167                                                                     uint32_t raw_data_00_31,
0168                                                                     uint32_t raw_data_32_63) {
0169   fillMuonCoordinatesFrom2017(mu, raw_data_00_31, raw_data_32_63);
0170 
0171   // displacement information
0172   mu.setHwDXY((raw_data_32_63 >> dxyShift_) & dxyMask_);
0173   mu.setHwPtUnconstrained((raw_data_00_31 >> ptUnconstrainedIntermedidateShift_) & ptUnconstrainedMask_);
0174 }
0175 
0176 void l1t::MuonRawDigiTranslator::generatePackedMuonDataWords(const Muon& mu,
0177                                                              uint32_t& raw_data_spare,
0178                                                              uint32_t& raw_data_00_31,
0179                                                              uint32_t& raw_data_32_63,
0180                                                              const int fedID,
0181                                                              const int fwID,
0182                                                              const int muInBx) {
0183   int abs_eta = mu.hwEta();
0184   if (abs_eta < 0) {
0185     abs_eta += (1 << (etaSignShift_ - absEtaShift_));
0186   }
0187   int abs_eta_at_vtx = mu.hwEtaAtVtx();
0188   if (abs_eta_at_vtx < 0) {
0189     abs_eta_at_vtx += (1 << (etaAtVtxSignShift_ - absEtaAtVtxShift_));
0190   }
0191   if ((fedID == kUgmtFedId && fwID < kUgmtFwVersionUntil2016) ||
0192       (fedID == kUgtFedId && fwID < kUgtFwVersionUntil2016)) {
0193     // For 2016 the non-extrapolated coordiantes were in the place that are now occupied by the extrapolated quantities.
0194     raw_data_spare = 0;
0195     raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
0196                      (abs_eta & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEta() < 0) << etaAtVtxSignShift_ |
0197                      (mu.hwPhi() & phiMask_) << phiAtVtxShift_;
0198     raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
0199                      (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_;
0200   } else if ((fedID == kUgmtFedId && fwID < kUgmtFwVersionUntil2017) ||
0201              (fedID == kUgtFedId && fwID < kUgtFwVersionUntil2017)) {
0202     raw_data_spare = 0;
0203     raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
0204                      (abs_eta_at_vtx & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEtaAtVtx() < 0) << etaAtVtxSignShift_ |
0205                      (mu.hwPhiAtVtx() & phiMask_) << phiAtVtxShift_;
0206 
0207     raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
0208                      (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_ |
0209                      (abs_eta & absEtaMask_) << absEtaShift_ | (mu.hwEta() < 0) << etaSignShift_ |
0210                      (mu.hwPhi() & phiMask_) << phiShift_;
0211   } else if ((fedID == kUgmtFedId && fwID == kUgmtFwVersionRun3Start) ||
0212              (fedID == kUgtFedId &&
0213               fwID < kUgtFwVersionUntilRun3Start)) {  // This allows us to unpack data taken in the November 2020 MWGR.
0214     generatePackedMuonDataWordsRun3(
0215         mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, true);
0216   } else {
0217     generatePackedMuonDataWordsRun3(
0218         mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, false);
0219   }
0220 }
0221 
0222 void l1t::MuonRawDigiTranslator::generatePackedMuonDataWordsRun3(const Muon& mu,
0223                                                                  const int abs_eta,
0224                                                                  const int abs_eta_at_vtx,
0225                                                                  uint32_t& raw_data_spare,
0226                                                                  uint32_t& raw_data_00_31,
0227                                                                  uint32_t& raw_data_32_63,
0228                                                                  const int muInBx,
0229                                                                  const bool wasSpecialMWGR /*= false*/) {
0230   int absEtaShiftRun3{0}, etaSignShiftRun3{0};
0231   if (muInBx == 1) {
0232     absEtaShiftRun3 = absEtaMu1Shift_;
0233     etaSignShiftRun3 = etaMu1SignShift_;
0234   } else if (muInBx == 2) {
0235     absEtaShiftRun3 = absEtaMu2Shift_;
0236     etaSignShiftRun3 = etaMu2SignShift_;
0237   }
0238 
0239   // Adjust if we're packing the November 2020 MWGR
0240   if (wasSpecialMWGR && (muInBx == 1 || muInBx == 2)) {
0241     --absEtaShiftRun3;
0242     --etaSignShiftRun3;
0243   }
0244 
0245   raw_data_spare = (abs_eta & absEtaMask_) << absEtaShiftRun3 | (mu.hwEta() < 0) << etaSignShiftRun3;
0246   raw_data_00_31 = (mu.hwPt() & ptMask_) << ptShift_ | (mu.hwQual() & qualMask_) << qualShift_ |
0247                    (abs_eta_at_vtx & absEtaMask_) << absEtaAtVtxShift_ | (mu.hwEtaAtVtx() < 0) << etaAtVtxSignShift_ |
0248                    (mu.hwPhiAtVtx() & phiMask_) << phiAtVtxShift_;
0249   raw_data_32_63 = mu.hwCharge() << chargeShift_ | mu.hwChargeValid() << chargeValidShift_ |
0250                    (mu.tfMuonIndex() & tfMuonIndexMask_) << tfMuonIndexShift_ | (mu.hwIso() & isoMask_) << isoShift_ |
0251                    (mu.hwPhi() & phiMask_) << phiShift_ |
0252                    (mu.hwPtUnconstrained() & ptUnconstrainedMask_) << ptUnconstrainedShift_ |
0253                    (mu.hwDXY() & dxyMask_) << dxyShift_;
0254 }
0255 
0256 void l1t::MuonRawDigiTranslator::generate64bitDataWord(
0257     const Muon& mu, uint32_t& raw_data_spare, uint64_t& dataword, int fedId, int fwId, int muInBx) {
0258   uint32_t lsw;
0259   uint32_t msw;
0260 
0261   generatePackedMuonDataWords(mu, raw_data_spare, lsw, msw, fedId, fwId, muInBx);
0262   dataword = (((uint64_t)msw) << 32) + lsw;
0263 }
0264 
0265 bool l1t::MuonRawDigiTranslator::isFwVersionWithShowers(int fedId, int fwId) {
0266   return ((fedId == kUgmtFedId && fwId >= kUgmtFwVersionFirstWithShowers) ||
0267           (fedId == kUgtFedId && fwId >= kUgtFwVersionFirstWithShowers));
0268 }
0269 
0270 bool l1t::MuonRawDigiTranslator::showerFired(uint32_t shower_word, int fedId, int fwId) {
0271   if (isFwVersionWithShowers(fedId, fwId)) {
0272     return ((shower_word >> showerShift_) & 1) == 1;
0273   }
0274   return false;
0275 }
0276 
0277 std::array<std::array<uint32_t, 4>, 2> l1t::MuonRawDigiTranslator::getPackedShowerDataWords(const MuonShower& shower,
0278                                                                                             const int fedId,
0279                                                                                             const int fwId) {
0280   std::array<std::array<uint32_t, 4>, 2> res{};
0281   if (isFwVersionWithShowers(fedId, fwId)) {
0282     res.at(0).at(0) = shower.isOneNominalInTime() ? (1 << showerShift_) : 0;
0283     res.at(0).at(1) = shower.isOneTightInTime() ? (1 << showerShift_) : 0;
0284   }
0285   if ((fedId == kUgmtFedId && fwId >= kUgmtFwVersionShowersFrom2023_patched) ||
0286       (fedId == kUgtFedId && fwId >= kUgtFwVersionShowersFrom2023)) {
0287     res.at(1).at(1) = shower.isTwoLooseDiffSectorsInTime()
0288                           ? (1 << showerShift_)
0289                           : 0;  // The two loose shower is on the second link in the second muon word.
0290   } else if (fedId == kUgmtFedId && fwId >= kUgmtFwVersionShowersFrom2023) {
0291     res.at(1).at(0) = shower.isTwoLooseDiffSectorsInTime()
0292                           ? (1 << showerShift_)
0293                           : 0;  // uGMT was briefly transmitting it on the first link instead.
0294   }
0295   return res;
0296 }
0297 
0298 int l1t::MuonRawDigiTranslator::calcHwEta(const uint32_t& raw,
0299                                           const unsigned absEtaShift,
0300                                           const unsigned etaSignShift) {
0301   // eta is coded as two's complement
0302   int abs_eta = (raw >> absEtaShift) & absEtaMask_;
0303   if ((raw >> etaSignShift) & 0x1) {
0304     return abs_eta - (1 << (etaSignShift - absEtaShift));
0305   } else {
0306     return abs_eta;
0307   }
0308 }