Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-02 23:19:46

0001 #include "L1Trigger/Phase2L1GMT/interface/TPSAlgorithm.h"
0002 
0003 using namespace Phase2L1GMT;
0004 
0005 TPSAlgorithm::TPSAlgorithm(const edm::ParameterSet& iConfig) : verbose_(iConfig.getParameter<int>("verbose")) {}
0006 
0007 std::vector<PreTrackMatchedMuon> TPSAlgorithm::processNonant(const std::vector<ConvertedTTTrack>& convertedTracks,
0008                                                              const l1t::MuonStubRefVector& stubs) const {
0009   std::vector<PreTrackMatchedMuon> preMuons;
0010   for (const auto& track : convertedTracks) {
0011     PreTrackMatchedMuon mu = processTrack(track, stubs);
0012     if (mu.valid() && preMuons.size() < 16)
0013       preMuons.push_back(mu);
0014   }
0015   std::vector<PreTrackMatchedMuon> cleanedMuons = clean(preMuons);
0016   return cleanedMuons;
0017 }
0018 
0019 std::vector<PreTrackMatchedMuon> TPSAlgorithm::cleanNeighbor(const std::vector<PreTrackMatchedMuon>& muons,
0020                                                              const std::vector<PreTrackMatchedMuon>& muonsPrevious,
0021                                                              const std::vector<PreTrackMatchedMuon>& muonsNext,
0022                                                              bool equality) const {
0023   std::vector<PreTrackMatchedMuon> out;
0024 
0025   if (muons.empty())
0026     return out;
0027 
0028   if (verbose_ == 1) {
0029     edm::LogInfo("TPSAlgo") << "-----Cleaning Up Muons in the neighbours";
0030     edm::LogInfo("TPSAlgo") << "Before:";
0031   }
0032 
0033   for (uint i = 0; i < muons.size(); ++i) {
0034     if (verbose_ == 1) {
0035       muons[i].print();
0036     }
0037     ap_uint<5> mask = 0x1f;
0038     for (uint j = 0; j < muonsPrevious.size(); ++j) {
0039       mask = mask & cleanMuon(muons[i], muonsPrevious[j], equality);
0040     }
0041     for (uint j = 0; j < muonsNext.size(); ++j) {
0042       mask = mask & cleanMuon(muons[i], muonsNext[j], equality);
0043     }
0044     if (mask) {
0045       if (verbose_ == 1)
0046         edm::LogInfo("TPSAlgo") << "kept";
0047       out.push_back(muons[i]);
0048     } else {
0049       if (verbose_ == 1)
0050         edm::LogInfo("TPSAlgo") << "discarded";
0051     }
0052   }
0053   return out;
0054 }
0055 
0056 std::vector<l1t::TrackerMuon> TPSAlgorithm::convert(const std::vector<PreTrackMatchedMuon>& muons, uint maximum) const {
0057   std::vector<l1t::TrackerMuon> out;
0058   for (const auto& mu : muons) {
0059     if (out.size() == maximum)
0060       break;
0061     l1t::TrackerMuon muon(mu.trkPtr(), mu.charge(), mu.pt(), mu.eta(), mu.phi(), mu.z0(), mu.d0(), mu.quality());
0062     muon.setMuonRef(mu.muonRef());
0063     for (const auto& stub : mu.stubs())
0064       muon.addStub(stub);
0065 
0066     uint matches = 0;
0067     uint mask = mu.matchMask();
0068 
0069     for (uint i = 0; i < 10; i = i + 1) {
0070       if (mask & (1 << i))
0071         matches++;
0072     }
0073     muon.setNumberOfMatches(matches);
0074     out.push_back(muon);
0075 
0076     if (verbose_ == 1) {
0077       edm::LogInfo("TPSAlgo") << "Final Muon:" << std::flush;
0078       muon.print();
0079     }
0080   }
0081   return out;
0082 }
0083 
0084 void TPSAlgorithm::SetQualityBits(std::vector<l1t::TrackerMuon>& muons) const {
0085   for (auto& mu : muons) {
0086     // A preliminary suggestion. Need feedback from the menu group
0087     bool veryloose = mu.numberOfMatches() > 0;
0088     bool loose = mu.numberOfMatches() > 1;
0089     bool medium = mu.stubs().size() > 1;
0090     bool tight = mu.numberOfMatches() > 2;
0091     int qualbit = 0;
0092     qualbit = (veryloose << 0) | (loose << 1) | (medium << 2) | (tight << 3);
0093     mu.setHwQual(qualbit);
0094   }
0095 }
0096 
0097 bool TPSAlgorithm::outputGT(std::vector<l1t::TrackerMuon>& muons) const {
0098   for (auto& mu : muons) {
0099     wordtype word1 = 0;
0100     wordtype word2 = 0;
0101 
0102     int bstart = 0;
0103     bstart = wordconcat<wordtype>(word1, bstart, mu.hwPt(), BITSGTPT);
0104     bstart = wordconcat<wordtype>(word1, bstart, mu.hwPhi(), BITSGTPHI);
0105     bstart = wordconcat<wordtype>(word1, bstart, mu.hwEta(), BITSGTETA);
0106     bstart = wordconcat<wordtype>(word1, bstart, mu.hwZ0(), BITSGTZ0);
0107     wordconcat<wordtype>(word1, bstart, (mu.hwD0() >> 2), BITSGTD0);
0108 
0109     bstart = 0;
0110     bstart = wordconcat<wordtype>(word2, bstart, mu.hwCharge(), 1);
0111     bstart = wordconcat<wordtype>(word2, bstart, mu.hwQual(), BITSGTQUAL);
0112     bstart = wordconcat<wordtype>(word2, bstart, mu.hwIso(), BITSGTISO);
0113     wordconcat<wordtype>(word2, bstart, mu.hwBeta(), BITSGTBETA);
0114 
0115     std::array<uint64_t, 2> wordout = {{word1, word2}};
0116     mu.setWord(wordout);
0117   }
0118   return true;
0119 }
0120 
0121 std::vector<l1t::TrackerMuon> TPSAlgorithm::sort(std::vector<l1t::TrackerMuon>& muons, uint maximum) const {
0122   if (muons.size() < 2)
0123     return muons;
0124 
0125   std::sort(muons.begin(), muons.end(), [](l1t::TrackerMuon a, l1t::TrackerMuon b) { return a.hwPt() > b.hwPt(); });
0126   std::vector<l1t::TrackerMuon> out{muons.begin(), muons.begin() + (maximum < muons.size() ? maximum : muons.size())};
0127 
0128   return out;
0129 }
0130 
0131 propagation_t TPSAlgorithm::propagate(const ConvertedTTTrack& track, uint layer) const {
0132   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop1_coord1 = {
0133       {lt_prop1_coord1_0, lt_prop1_coord1_1, lt_prop1_coord1_2, lt_prop1_coord1_3, lt_prop1_coord1_4}};
0134   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop1_coord2 = {
0135       {lt_prop1_coord2_0, lt_prop1_coord2_1, lt_prop1_coord2_2, lt_prop1_coord2_3, lt_prop1_coord2_4}};
0136   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop2_coord1 = {
0137       {lt_prop2_coord1_0, lt_prop2_coord1_1, lt_prop2_coord1_2, lt_prop2_coord1_3, lt_prop2_coord1_4}};
0138   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop2_coord2 = {
0139       {lt_prop2_coord2_0, lt_prop2_coord2_1, lt_prop2_coord2_2, lt_prop2_coord2_3, lt_prop2_coord2_4}};
0140   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop3_coord1 = {
0141       {lt_prop3_coord1_0, lt_prop3_coord1_1, lt_prop3_coord1_2, lt_prop3_coord1_3, lt_prop3_coord1_4}};
0142   static const std::array<const ap_uint<BITSPROPCOORD>*, 5> lt_prop3_coord2 = {
0143       {lt_prop3_coord2_0, lt_prop3_coord2_1, lt_prop3_coord2_2, lt_prop3_coord2_3, lt_prop3_coord2_4}};
0144 
0145   static const std::array<const ap_uint<BITSPROPSIGMACOORD_A>*, 5> lt_res0_coord1 = {
0146       {lt_res0_coord1_0, lt_res0_coord1_1, lt_res0_coord1_2, lt_res0_coord1_3, lt_res0_coord1_4}};
0147   static const std::array<const ap_uint<BITSPROPSIGMACOORD_B>*, 5> lt_res1_coord1 = {
0148       {lt_res1_coord1_0, lt_res1_coord1_1, lt_res1_coord1_2, lt_res1_coord1_3, lt_res1_coord1_4}};
0149   static const std::array<const ap_uint<BITSPROPSIGMACOORD_A>*, 5> lt_res0_coord2 = {
0150       {lt_res0_coord2_0, lt_res0_coord2_1, lt_res0_coord2_2, lt_res0_coord2_3, lt_res0_coord2_4}};
0151   static const std::array<const ap_uint<BITSPROPSIGMACOORD_B>*, 5> lt_res1_coord2 = {
0152       {lt_res1_coord2_0, lt_res1_coord2_1, lt_res1_coord2_2, lt_res1_coord2_3, lt_res1_coord2_4}};
0153 
0154   static const std::array<const ap_uint<BITSPROPSIGMAETA_A>*, 5> lt_res0_eta1 = {
0155       {lt_res0_eta1_0, lt_res0_eta1_1, lt_res0_eta1_2, lt_res0_eta1_3, lt_res0_eta1_4}};
0156   static const std::array<const ap_uint<BITSPROPSIGMAETA_A>*, 5> lt_res1_eta1 = {
0157       {lt_res1_eta_0, lt_res1_eta_1, lt_res1_eta_2, lt_res1_eta_3, lt_res1_eta_4}};
0158 
0159   static const std::array<const ap_uint<BITSPROPSIGMAETA_A>*, 5> lt_res0_eta2 = {
0160       {lt_res0_eta2_0, lt_res0_eta2_1, lt_res0_eta2_2, lt_res0_eta2_3, lt_res0_eta2_4}};
0161 
0162   static const uint barrellimit[5] = {barrelLimit0_, barrelLimit1_, barrelLimit2_, barrelLimit3_, barrelLimit4_};
0163 
0164   ap_uint<BITSPROPCOORD> prop1_coord1 = 0;
0165   ap_uint<BITSPROPCOORD> prop2_coord1 = 0;
0166   ap_uint<BITSPROPCOORD> prop3_coord1 = 0;
0167   ap_uint<BITSPROPCOORD> prop1_coord2 = 0;
0168   ap_uint<BITSPROPCOORD> prop2_coord2 = 0;
0169   ap_uint<BITSPROPCOORD> prop3_coord2 = 0;
0170   ap_uint<BITSPROPSIGMACOORD_A> res0_coord1 = 0;
0171   ap_uint<BITSPROPSIGMACOORD_B> res1_coord1 = 0;
0172   ap_uint<BITSPROPSIGMACOORD_A> res0_coord2 = 0;
0173   ap_uint<BITSPROPSIGMACOORD_B> res1_coord2 = 0;
0174   ap_uint<BITSPROPSIGMAETA_A> res0_eta1 = 0;
0175   ap_uint<BITSPROPSIGMAETA_B> res1_eta = 0;
0176   ap_uint<BITSPROPSIGMAETA_A> res0_eta2 = 0;
0177   ap_uint<1> is_barrel = 0;
0178 
0179   //1 extra bit to sense overflows, 1 for sign
0180   ap_int<BITSPROP + 2> dphi_c1 = 0;
0181   ap_int<BITSPROP + 2> dphi_c2 = 0;
0182 
0183   uint reducedAbsEta = track.abseta() / 8;
0184 
0185   //Propagate to layers
0186   assert(layer < 5);
0187   prop1_coord1 = lt_prop1_coord1[layer][reducedAbsEta];
0188   prop2_coord1 = lt_prop2_coord1[layer][reducedAbsEta];
0189   prop3_coord1 = lt_prop3_coord1[layer][reducedAbsEta];
0190   prop1_coord2 = lt_prop1_coord2[layer][reducedAbsEta];
0191   prop2_coord2 = lt_prop2_coord2[layer][reducedAbsEta];
0192   prop3_coord2 = lt_prop3_coord2[layer][reducedAbsEta];
0193 
0194   res0_coord1 = lt_res0_coord1[layer][reducedAbsEta];
0195   res1_coord1 = lt_res1_coord1[layer][reducedAbsEta];
0196   res0_coord2 = lt_res0_coord2[layer][reducedAbsEta];
0197   res1_coord2 = lt_res1_coord2[layer][reducedAbsEta];
0198   res0_eta1 = lt_res0_eta1[layer][reducedAbsEta];
0199   res1_eta = lt_res1_eta1[layer][reducedAbsEta];
0200   res0_eta2 = lt_res0_eta2[layer][reducedAbsEta];
0201   is_barrel = reducedAbsEta < barrellimit[layer] ? 1 : 0;
0202 
0203   //try inflating res0's
0204   //res0_coord1 = 2 * res0_coord1;
0205   //res0_coord2 = 2 * res0_coord2;
0206 
0207   propagation_t out;
0208   ap_int<BITSTTCURV> k = track.curvature();
0209   ap_int<BITSPHI> phi = track.phi();
0210 
0211   ap_uint<BITSTTCURV - 1> absK = 0;
0212   ap_uint<1> negativeCurv = 0;
0213   if (k < 0) {
0214     absK = ap_uint<BITSTTCURV - 1>(-k);
0215     negativeCurv = 1;
0216   } else {
0217     absK = ap_uint<BITSTTCURV - 1>(k);
0218   }
0219 
0220   ap_uint<2 * BITSTTCURV - 2> k2All = k * k;  //to match firmware
0221   ap_uint<BITSTTCURV2> k2 = k2All / 2;
0222 
0223   //coord 1 propagation is c*k + d*k^2 for low k, c*k + d*k_cutoff^2 + 2d*k_cutoff*(k - k_cutoff) + e*(k - k_cutoff)^2 for high k (above cutoff)
0224   //decomposed into bitshifts here for firmware
0225   ap_uint<BITSPROPCOORD + BITSTTCURV - 1> dphi_c1Full = prop1_coord1 * absK;
0226   dphi_c1 = dphi_c1Full >> BITSHIFTPROP1C1;
0227 
0228   if (absK <= (1 << BITSHIFTCURVSCALEC1)) {
0229     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2> dphi2_c1Full = prop2_coord1 * k2;
0230     dphi_c1 += (dphi2_c1Full >> (BITSHIFTPROP2C1 - 1));  //- because k2 already did one shift
0231   } else {
0232     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2 + BITSHIFTCURVSCALEC1 + 1> dphi2A_c1Full = prop2_coord1 * absK;
0233     dphi_c1 += ((dphi2A_c1Full << (BITSHIFTCURVSCALEC1 + 1)) >> BITSHIFTPROP2C1);
0234     ap_uint<BITSPROPCOORD + 2 * BITSHIFTCURVSCALEC1> dphi2B_c1Full = prop2_coord1;
0235     dphi_c1 -= (dphi2B_c1Full << (2 * BITSHIFTCURVSCALEC1)) >> BITSHIFTPROP2C1;
0236 
0237     ap_uint<BITSTTCURV2 + 1> k2pad = k2;
0238     ap_uint<BITSTTCURV - 1 + BITSHIFTCURVSCALEC1 + 1> absKpad = absK;
0239     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2> dphi3_c1Full =
0240         (k2pad << 1) + (1 << (2 * BITSHIFTCURVSCALEC1)) - (absKpad << (BITSHIFTCURVSCALEC1 + 1));
0241     dphi3_c1Full *= prop3_coord1;
0242     dphi_c1 += (dphi3_c1Full >> BITSHIFTPROP3C1);
0243   }
0244 
0245   if (dphi_c1 > PROPMAX)  //c1 should only propagate in one direction, no abs needed
0246     dphi_c1 = PROPMAX;
0247 
0248   //subtract the magnitude for positive k, add the magnitude for negative k
0249   if (negativeCurv == 0)
0250     dphi_c1 = -dphi_c1;
0251 
0252   out.coord1 = ((phi + dphi_c1) >> PHISHIFT);
0253 
0254   //coord 2 propagation is of the same functional form as coord 1 but now the 3rd coefficient e can be negative and the cutoff curvatures vary as a function of tflayer
0255   //in particular layer 1 has a cutoff that is not an exponent of 2 so we store it as a difference of exponents of 2 below (2^LEADS - 2^CORRS)
0256   ap_uint<BITSPROPCOORD + BITSTTCURV - 1> dphi_c2Full = prop1_coord2 * absK;
0257   dphi_c2 = dphi_c2Full >> BITSHIFTPROP1C2;
0258 
0259   if (absK <= ((1 << (BITSHIFTCURVSCALEC2LEADS[layer])) - (1 << (BITSHIFTCURVSCALEC2CORRS[layer])))) {
0260     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2> dphi2_c2Full = prop2_coord2 * k2;
0261     dphi_c2 += (dphi2_c2Full >> (BITSHIFTPROP2C2 - 1));  //-1 because k2 already did one shift
0262   } else {
0263     ap_uint<BITSTTCURV2 + 1> k2pad = k2;
0264     ap_uint<BITSTTCURV - 1 + BITSTTCURV> absKpad = absK;  //bitsttcurv gives enough padding
0265 
0266     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2> dphi2_c2Full =
0267         (absKpad << (BITSHIFTCURVSCALEC2LEADS[layer] + 1)) - (1 << (2 * BITSHIFTCURVSCALEC2LEADS[layer]));
0268     if (BITSHIFTCURVSCALEC2CORRS[layer] != 0) {
0269       dphi2_c2Full += (1 << (BITSHIFTCURVSCALEC2LEADS[layer] + BITSHIFTCURVSCALEC2CORRS[layer] + 1));
0270       dphi2_c2Full -=
0271           ((absKpad << (BITSHIFTCURVSCALEC2CORRS[layer] + 1)) + (1 << (2 * BITSHIFTCURVSCALEC2CORRS[layer])));
0272     }
0273     dphi_c2 += (dphi2_c2Full >> BITSHIFTPROP2C2);
0274 
0275     ap_uint<BITSPROPCOORD + 2 * BITSTTCURV - 2> dphi3_c2Full = (k2pad << 1) +
0276                                                                (1 << (2 * BITSHIFTCURVSCALEC2LEADS[layer])) -
0277                                                                (absKpad << (BITSHIFTCURVSCALEC2LEADS[layer] + 1));
0278     if (BITSHIFTCURVSCALEC2CORRS[layer] != 0) {
0279       dphi3_c2Full +=
0280           ((1 << (2 * BITSHIFTCURVSCALEC2CORRS[layer])) + (absKpad << (BITSHIFTCURVSCALEC2CORRS[layer] + 1)));
0281       dphi3_c2Full -= (1 << (BITSHIFTCURVSCALEC2LEADS[layer] + BITSHIFTCURVSCALEC2CORRS[layer] + 1));
0282     }
0283     dphi3_c2Full *= prop3_coord2;
0284     if (layer == 0 or layer == 4) {
0285       dphi_c2 += (dphi3_c2Full >> BITSHIFTPROP3C2);
0286     } else {
0287       dphi_c2 -= (dphi3_c2Full >> BITSHIFTPROP3C2);
0288     }
0289   }
0290 
0291   if (dphi_c2 > PROPMAX)
0292     dphi_c2 = PROPMAX;
0293   else if (dphi_c2 < -PROPMAX)
0294     dphi_c2 = -PROPMAX;
0295 
0296   //subtract the magnitude for positive k, add the magnitude for negative k
0297   if (negativeCurv == 0)
0298     dphi_c2 = -dphi_c2;
0299 
0300   if (is_barrel)
0301     out.coord2 = (dphi_c2 >> PHISHIFT);
0302   else
0303     out.coord2 = ((phi + dphi_c2) >> PHISHIFT);
0304 
0305   ap_uint<BITSPROPSIGMACOORD_B + BITSTTCURV - 1> s1kFull = res1_coord1 * absK;
0306   ap_uint<BITSPROPSIGMACOORD_B + BITSTTCURV - 1 - BITSHIFTRES1> s1k = res0_coord1 + (s1kFull >> BITSHIFTRES1);
0307   s1k = s1k >> PHISHIFT;
0308   if (s1k >= SIGMAMAX)
0309     out.sigma_coord1 = SIGMAMAX;
0310   else if (s1k < SIGMAMIN)
0311     out.sigma_coord1 = SIGMAMIN;
0312   else
0313     out.sigma_coord1 = s1k;
0314 
0315   ap_uint<BITSPROPSIGMACOORD_B + BITSTTCURV - 1> s2kFull = res1_coord2 * absK;
0316   ap_uint<BITSPROPSIGMACOORD_B + BITSTTCURV - 1 - BITSHIFTRES1> s2k = res0_coord2 + (s2kFull >> BITSHIFTRES1);
0317   s2k = s2k >> PHISHIFT;
0318   if (s2k >= SIGMAMAX)
0319     out.sigma_coord2 = SIGMAMAX;
0320   else if (s2k < SIGMAMIN)
0321     out.sigma_coord2 = SIGMAMIN;
0322   else
0323     out.sigma_coord2 = s2k;
0324 
0325   ap_int<BITSETA> eta = track.eta();
0326   out.eta = eta / ETADIVIDER;
0327   //out.eta = eta >> ETASHIFT;
0328 
0329   ap_uint<BITSPROPSIGMAETA_B + BITSTTCURV2> resetak = (res1_eta * k2) >> 23;
0330   ap_ufixed<BITSSIGMAETA, BITSSIGMAETA, AP_TRN_ZERO, AP_SAT_SYM> sigma_eta1 = res0_eta1 + resetak;
0331   out.sigma_eta1 = ap_uint<BITSSIGMAETA>(sigma_eta1);
0332   ap_ufixed<BITSSIGMAETA, BITSSIGMAETA, AP_TRN_ZERO, AP_SAT_SYM> sigma_eta2 = res0_eta2 + resetak;
0333   out.sigma_eta2 = ap_uint<BITSSIGMAETA>(sigma_eta2);
0334 
0335   out.valid = 1;
0336   out.is_barrel = is_barrel;
0337 
0338   if (verbose_ == 1) {
0339     edm::LogInfo("TPSAlgo") << "Propagating to layer " << int(layer) << ":is barrel=" << out.is_barrel.to_int()
0340                             << "  coords=" << out.coord1.to_int() << "+-" << out.sigma_coord1.to_int() << " , "
0341                             << out.coord2.to_int() << " +-" << out.sigma_coord2.to_int()
0342                             << " etas = " << out.eta.to_int() << " +- " << out.sigma_eta1.to_int() << " +-"
0343                             << out.sigma_eta2.to_int();
0344 
0345     edm::LogInfo("TPSAlgo") << "----- breakout of sigma 1 : constant=" << res0_coord1.to_int()
0346                             << " slope=" << res1_coord1.to_int() << " before division=" << s1k.to_int();
0347 
0348     edm::LogInfo("TPSAlgo") << "----- breakout of sigma 2 : constant=" << res0_coord2.to_int()
0349                             << " slope=" << res1_coord2.to_int() << " before division=" << s2k.to_int();
0350   }
0351   return out;
0352 }
0353 
0354 ap_uint<BITSSIGMAETA + 1> TPSAlgorithm::deltaEta(const ap_int<BITSSTUBETA>& eta1,
0355                                                  const ap_int<BITSSTUBETA>& eta2) const {
0356   ap_fixed<BITSSIGMAETA + 2, BITSSIGMAETA + 2, AP_TRN_ZERO, AP_SAT_SYM> dEta = eta1 - eta2;
0357   if (dEta < 0)
0358     return ap_uint<BITSSIGMAETA + 1>(-dEta);
0359   else
0360     return ap_uint<BITSSIGMAETA + 1>(dEta);
0361 }
0362 
0363 ap_uint<BITSSIGMACOORD + 1> TPSAlgorithm::deltaCoord(const ap_int<BITSSTUBCOORD>& phi1,
0364                                                      const ap_int<BITSSTUBCOORD>& phi2) const {
0365   ap_int<BITSSTUBCOORD> dPhiRoll = phi1 - phi2;
0366   ap_ufixed<BITSSIGMACOORD + 1, BITSSIGMACOORD + 1, AP_TRN_ZERO, AP_SAT_SYM> dPhi;
0367   if (dPhiRoll < 0)
0368     dPhi = ap_ufixed<BITSSIGMACOORD + 1, BITSSIGMACOORD + 1, AP_TRN_ZERO, AP_SAT_SYM>(-dPhiRoll);
0369   else
0370     dPhi = ap_ufixed<BITSSIGMACOORD + 1, BITSSIGMACOORD + 1, AP_TRN_ZERO, AP_SAT_SYM>(dPhiRoll);
0371 
0372   return ap_uint<BITSSIGMACOORD + 1>(dPhi);
0373 }
0374 
0375 match_t TPSAlgorithm::match(const propagation_t prop, const l1t::MuonStubRef& stub, uint trackID) const {
0376   if (verbose_ == 1) {
0377     edm::LogInfo("TPSAlgo") << "Matching to coord1=" << stub->coord1() << " coord2=" << stub->coord2()
0378                             << " eta1=" << stub->eta1() << " eta2=" << stub->eta2();
0379 
0380     stub->print();
0381   }
0382   //Matching of Coord1
0383   ap_uint<1> coord1Matched;
0384   ap_uint<BITSSIGMACOORD + 1> deltaCoord1 = deltaCoord(prop.coord1, stub->coord1());
0385   if (deltaCoord1 <= prop.sigma_coord1 && (stub->quality() & 0x1)) {
0386     coord1Matched = 1;
0387   } else {
0388     coord1Matched = 0;
0389   }
0390   if (verbose_ == 1)
0391     edm::LogInfo("TPSAlgo") << "Coord1 matched=" << coord1Matched.to_int() << " delta=" << deltaCoord1.to_int()
0392                             << " res=" << prop.sigma_coord1.to_int();
0393 
0394   //Matching of Coord2
0395   ap_uint<1> coord2Matched;
0396   ap_uint<BITSSIGMACOORD + 1> deltaCoord2 = deltaCoord(prop.coord2, stub->coord2());
0397   if (deltaCoord2 <= prop.sigma_coord2 && (stub->quality() & 0x2)) {
0398     coord2Matched = 1;
0399   } else {
0400     coord2Matched = 0;
0401   }
0402   if (verbose_ == 1)
0403     edm::LogInfo("TPSAlgo") << "Coord2 matched=" << coord2Matched.to_int() << " delta=" << deltaCoord2.to_int()
0404                             << " res=" << prop.sigma_coord2.to_int();
0405 
0406   //Matching of Eta1
0407 
0408   ap_uint<1> eta1Matched;
0409 
0410   //if we have really bad quality[Barrel no eta]
0411   //increase the resolution
0412   ap_ufixed<BITSSIGMAETA, BITSSIGMAETA, AP_TRN_ZERO, AP_SAT_SYM> prop_sigma_eta1;
0413   if (stub->etaQuality() == 0)
0414     prop_sigma_eta1 = prop.sigma_eta1 + 6;
0415   else
0416     prop_sigma_eta1 = prop.sigma_eta1;
0417 
0418   ap_uint<BITSSIGMAETA + 1> deltaEta1 = deltaEta(prop.eta, stub->eta1());
0419   if (deltaEta1 <= prop_sigma_eta1 && (stub->etaQuality() == 0 || (stub->etaQuality() & 0x1)))
0420     eta1Matched = 1;
0421   else
0422     eta1Matched = 0;
0423 
0424   if (verbose_ == 1)
0425     edm::LogInfo("TPSAlgo") << "eta1 matched=" << eta1Matched.to_int() << " delta=" << deltaEta1.to_int()
0426                             << " res=" << prop_sigma_eta1.to_int();
0427 
0428   //Matching of Eta2
0429 
0430   ap_uint<1> eta2Matched;
0431 
0432   ap_uint<BITSSIGMAETA + 1> deltaEta2 = deltaEta(prop.eta, stub->eta2());
0433   if (deltaEta2 <= prop.sigma_eta2 && (stub->etaQuality() & 0x2))
0434     eta2Matched = 1;
0435   else
0436     eta2Matched = 0;
0437   match_t out;
0438   out.id = trackID;
0439 
0440   if (verbose_ == 1)
0441     edm::LogInfo("TPSAlgo") << "eta2 matched=" << eta2Matched.to_int() << " delta=" << deltaEta2.to_int()
0442                             << " res=" << prop.sigma_eta2.to_int();
0443 
0444   //Note I divided by 4 because of the new coordinate. Make it automatic
0445 
0446   //if barrel, coord1 has to always be matched, coord2 maybe and eta1 is needed if etaQ=0 or then the one that depends on eta quality
0447   if (prop.is_barrel) {
0448     out.valid = (coord1Matched == 1 && (eta1Matched == 1 || eta2Matched == 1)) ? 1 : 0;
0449     if (out.valid == 0) {
0450       out.quality = 0;
0451     } else {
0452       out.quality = 32 - deltaCoord1 / 4;
0453       if (coord2Matched == 1) {
0454         out.quality += 32 - deltaCoord2 / 4;
0455         out.valid = 3;
0456       }
0457     }
0458   }
0459   //if endcap each coordinate is independent except the case where phiQuality=1 and etaQuality==3
0460   else {
0461     bool match1 = (coord1Matched == 1 && eta1Matched == 1);
0462     bool match2 = (coord2Matched == 1 && eta2Matched == 1);
0463     bool match3 =
0464         (coord1Matched == 1 && (eta1Matched || eta2Matched) && stub->etaQuality() == 3 && stub->quality() == 1);
0465     out.valid = (match1 || match2 || match3) ? 1 : 0;
0466     if (out.valid == 0)
0467       out.quality = 0;
0468     else {
0469       out.quality = 0;
0470       if (match1 || match3)
0471         out.quality += 32 - deltaCoord1 / 4;
0472       if (match2) {
0473         out.quality += 32 - deltaCoord2 / 4;
0474         if (match1 || match3)
0475           out.valid = 3;
0476       }
0477     }
0478   }
0479   if (verbose_ == 1)
0480     edm::LogInfo("TPSAlgo") << "GlobalMatchQuality = " << out.quality.to_int();
0481   out.stubRef = stub;
0482   return out;
0483 }
0484 
0485 match_t TPSAlgorithm::propagateAndMatch(const ConvertedTTTrack& track,
0486                                         const l1t::MuonStubRef& stub,
0487                                         uint trackID) const {
0488   propagation_t prop = propagate(track, stub->tfLayer());
0489   return match(prop, stub, trackID);
0490 }
0491 
0492 match_t TPSAlgorithm::getBest(const std::vector<match_t>& matches) const {
0493   match_t best = matches[0];
0494   for (const auto& m : matches) {
0495     if (m.quality > best.quality)
0496       best = m;
0497   }
0498 
0499   return best;
0500 }
0501 
0502 void TPSAlgorithm::matchingInfos(const std::vector<match_t>& matchInfo,
0503                                  PreTrackMatchedMuon& muon,
0504                                  ap_uint<BITSMATCHQUALITY>& quality) const {
0505   if (!matchInfo.empty()) {
0506     match_t b = getBest(matchInfo);
0507     if (b.valid != 0) {
0508       muon.addStub(b.stubRef, b.valid);
0509       if (b.isGlobal)
0510         muon.addMuonRef(b.muRef);
0511       quality += b.quality;
0512     }
0513   }
0514 }
0515 
0516 PreTrackMatchedMuon TPSAlgorithm::processTrack(const ConvertedTTTrack& track,
0517                                                const l1t::MuonStubRefVector& stubs) const {
0518   std::array<std::vector<match_t>, 6> matchInfos;
0519 
0520   if (verbose_ == 1 && !stubs.empty()) {
0521     edm::LogInfo("TPSAlgo") << "-----------processing new track----------";
0522     track.print();
0523   }
0524   for (const auto& stub : stubs) {
0525     match_t m = propagateAndMatch(track, stub, 0);
0526     if (m.valid != 0 && stub->tfLayer() < 6) {
0527       matchInfos[stub->tfLayer()].push_back(m);
0528     }
0529   }
0530 
0531   ap_ufixed<6, 6, AP_TRN_ZERO, AP_SAT_SYM> ptPenalty = ap_ufixed<6, 6, AP_TRN_ZERO, AP_SAT_SYM>(track.pt() / 32);
0532 
0533   ap_uint<BITSMATCHQUALITY> quality = 0;
0534   PreTrackMatchedMuon muon(track.charge(), track.pt(), track.eta(), track.phi(), track.z0(), track.d0());
0535 
0536   for (auto&& m : matchInfos)
0537     matchingInfos(m, muon, quality);
0538 
0539   muon.setOfflineQuantities(track.offline_pt(), track.offline_eta(), track.offline_phi());
0540   muon.setTrkPtr(track.trkPtr());
0541 
0542   ap_uint<8> etaAddr = muon.eta() < 0 ? ap_uint<8>(-muon.eta() / 256) : ap_uint<8>((muon.eta()) / 256);
0543   ap_uint<8> ptAddr = muon.pt() > 4095 ? ap_uint<8>(15) : ap_uint<8>(muon.pt() / 256);
0544   ap_uint<8> addr = ptAddr | (etaAddr << 4);
0545   ap_uint<8> qualityCut = lt_tpsID[addr];
0546 
0547   if (!muon.stubs().empty()) {  //change the ID for now
0548     muon.setValid(true);
0549     muon.setQuality(quality + ptPenalty);
0550   } else {
0551     muon.setValid(false);
0552     muon.setQuality(0);
0553     muon.resetGlobal();
0554   }
0555   if (verbose_ == 1)
0556     muon.print();
0557 
0558   if (verbose_ == 1 && !stubs.empty()) {  //patterns for HLS
0559 
0560     edm::LogInfo("TPSAlgo") << "TPS " << track.trkPtr()->phiSector() << std::flush;
0561     track.printWord();
0562 
0563     for (uint i = 0; i < 16; ++i) {
0564       if (stubs.size() > i) {
0565         edm::LogInfo("TPSAlgo") << "remember to implement printout of muon";
0566       } else {
0567         edm::LogInfo("TPSAlgo") << std::hex << std::setw(8) << 0 << std::flush;
0568         edm::LogInfo("TPSAlgo") << std::hex << std::setw(16) << 0x1ff000000000000 << std::flush;
0569         edm::LogInfo("TPSAlgo") << std::hex << std::setw(16) << 0x1ff000000000000 << std::flush;
0570         edm::LogInfo("TPSAlgo") << std::hex << std::setw(16) << 0x1ff000000000000 << std::flush;
0571         edm::LogInfo("TPSAlgo") << std::hex << std::setw(16) << 0x1ff000000000000 << std::flush;
0572         edm::LogInfo("TPSAlgo") << std::hex << std::setw(16) << 0x1ff000000000000 << std::flush;
0573       }
0574     }
0575     muon.printWord();
0576     edm::LogInfo("TPSAlgo") << std::endl;
0577   }
0578 
0579   return muon;
0580 }
0581 
0582 ap_uint<5> TPSAlgorithm::cleanMuon(const PreTrackMatchedMuon& mu, const PreTrackMatchedMuon& other, bool eq) const {
0583   ap_uint<5> valid = 0;
0584   ap_uint<5> overlap = 0;
0585   constexpr int bittest = 0xfff;  // 4095, corresponding to 11bits
0586   if (mu.stubID0() != bittest) {
0587     valid = valid | 0x1;
0588     if (mu.stubID0() == other.stubID0())
0589       overlap = overlap | 0x1;
0590   }
0591   if (mu.stubID1() != bittest) {
0592     valid = valid | 0x2;
0593     if (mu.stubID1() == other.stubID1())
0594       overlap = overlap | 0x2;
0595   }
0596   if (mu.stubID2() != bittest) {
0597     valid = valid | 0x4;
0598     if (mu.stubID2() == other.stubID2())
0599       overlap = overlap | 0x4;
0600   }
0601   if (mu.stubID3() != bittest) {
0602     valid = valid | 0x8;
0603     if (mu.stubID3() == other.stubID3())
0604       overlap = overlap | 0x8;
0605   }
0606   if (mu.stubID4() != bittest) {
0607     valid = valid | 0x10;
0608     if (mu.stubID4() == other.stubID4())
0609       overlap = overlap | 0x10;
0610   }
0611 
0612   if (((mu.quality() < other.quality()) && (!eq)) || ((mu.quality() <= other.quality()) && (eq)))
0613     return valid & (~overlap);
0614   else
0615     return valid;
0616 }
0617 
0618 std::vector<PreTrackMatchedMuon> TPSAlgorithm::clean(const std::vector<PreTrackMatchedMuon>& muons) const {
0619   std::vector<PreTrackMatchedMuon> out;
0620   if (muons.empty())
0621     return out;
0622   if (verbose_ == 1) {
0623     edm::LogInfo("TPSAlgo") << "-----Cleaning Up Muons in the same Nonant";
0624     edm::LogInfo("TPSAlgo") << "Before:";
0625   }
0626   for (uint i = 0; i < muons.size(); ++i) {
0627     if (verbose_ == 1)
0628       muons[i].print();
0629 
0630     ap_uint<5> mask = 0x1f;
0631     for (uint j = 0; j < muons.size(); ++j) {
0632       if (i == j)
0633         continue;
0634       mask = mask & cleanMuon(muons[i], muons[j], false);
0635     }
0636     if (mask) {
0637       if (verbose_ == 1)
0638         edm::LogInfo("TPSAlgo") << "kept";
0639       out.push_back(muons[i]);
0640     } else {
0641       if (verbose_ == 1)
0642         edm::LogInfo("TPSAlgo") << "discarded";
0643     }
0644   }
0645   return out;
0646 }