File indexing completed on 2024-07-12 23:00:02
0001 #include <cmath>
0002 #include "L1Trigger/L1TMuonBarrel/interface/L1TMuonBarrelKalmanAlgo.h"
0003 #include "ap_int.h"
0004 #include "ap_fixed.h"
0005
0006 L1TMuonBarrelKalmanAlgo::L1TMuonBarrelKalmanAlgo(const edm::ParameterSet& settings)
0007 : verbose_(settings.getParameter<bool>("verbose")),
0008 lutService_(new L1TMuonBarrelKalmanLUTs(settings.getParameter<std::string>("lutFile"))),
0009 initK_(settings.getParameter<std::vector<double> >("initialK")),
0010 initK2_(settings.getParameter<std::vector<double> >("initialK2")),
0011 eLoss_(settings.getParameter<std::vector<double> >("eLoss")),
0012 aPhi_(settings.getParameter<std::vector<double> >("aPhi")),
0013 aPhiB_(settings.getParameter<std::vector<double> >("aPhiB")),
0014 aPhiBNLO_(settings.getParameter<std::vector<double> >("aPhiBNLO")),
0015 bPhi_(settings.getParameter<std::vector<double> >("bPhi")),
0016 bPhiB_(settings.getParameter<std::vector<double> >("bPhiB")),
0017 phiAt2_(settings.getParameter<double>("phiAt2")),
0018
0019 chiSquare_(settings.getParameter<std::vector<double> >("chiSquare")),
0020 chiSquareCutPattern_(settings.getParameter<std::vector<int> >("chiSquareCutPattern")),
0021 chiSquareCutCurv_(settings.getParameter<std::vector<int> >("chiSquareCutCurvMax")),
0022 chiSquareCut_(settings.getParameter<std::vector<int> >("chiSquareCut")),
0023 trackComp_(settings.getParameter<std::vector<double> >("trackComp")),
0024 trackCompErr1_(settings.getParameter<std::vector<double> >("trackCompErr1")),
0025 trackCompErr2_(settings.getParameter<std::vector<double> >("trackCompErr2")),
0026 trackCompPattern_(settings.getParameter<std::vector<int> >("trackCompCutPattern")),
0027 trackCompCutCurv_(settings.getParameter<std::vector<int> >("trackCompCutCurvMax")),
0028 trackCompCut_(settings.getParameter<std::vector<int> >("trackCompCut")),
0029 chiSquareCutTight_(settings.getParameter<std::vector<int> >("chiSquareCutTight")),
0030 combos4_(settings.getParameter<std::vector<int> >("combos4")),
0031 combos3_(settings.getParameter<std::vector<int> >("combos3")),
0032 combos2_(settings.getParameter<std::vector<int> >("combos2")),
0033 combos1_(settings.getParameter<std::vector<int> >("combos1")),
0034
0035 useOfflineAlgo_(settings.getParameter<bool>("useOfflineAlgo")),
0036 mScatteringPhi_(settings.getParameter<std::vector<double> >("mScatteringPhi")),
0037 mScatteringPhiB_(settings.getParameter<std::vector<double> >("mScatteringPhiB")),
0038 pointResolutionPhi_(settings.getParameter<double>("pointResolutionPhi")),
0039 pointResolutionPhiB_(settings.getParameter<double>("pointResolutionPhiB")),
0040 pointResolutionPhiBH_(settings.getParameter<std::vector<double> >("pointResolutionPhiBH")),
0041 pointResolutionPhiBL_(settings.getParameter<std::vector<double> >("pointResolutionPhiBL")),
0042 pointResolutionVertex_(settings.getParameter<double>("pointResolutionVertex")),
0043 useNewQualityCalculation_(settings.getParameter<bool>("useNewQualityCalculation"))
0044
0045 {}
0046
0047 std::pair<bool, uint> L1TMuonBarrelKalmanAlgo::getByCode(const L1MuKBMTrackCollection& tracks, int mask) {
0048 for (uint i = 0; i < tracks.size(); ++i) {
0049 printf("Code=%d, track=%d\n", tracks[i].hitPattern(), mask);
0050 if (tracks[i].hitPattern() == mask)
0051 return std::make_pair(true, i);
0052 }
0053 return std::make_pair(false, 0);
0054 }
0055
0056 l1t::RegionalMuonCand L1TMuonBarrelKalmanAlgo::convertToBMTF(const L1MuKBMTrack& track) {
0057
0058
0059
0060 int sign, signValid;
0061
0062 if (track.curvatureAtVertex() == 0) {
0063 sign = 0;
0064 signValid = 0;
0065 } else if (track.curvatureAtVertex() > 0) {
0066 sign = 0;
0067 signValid = 1;
0068 } else {
0069 sign = 1;
0070 signValid = 1;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079 int pt = ptLUT(track.curvatureAtVertex());
0080
0081
0082
0083
0084
0085
0086
0087 int pt2 = ptLUT(track.curvatureAtMuon()) / 2;
0088 int eta = track.hasFineEta() ? track.fineEta() : track.coarseEta();
0089
0090
0091
0092
0093
0094
0095
0096 int phi2 = track.phiAtMuon() >> 2;
0097 int tmp = fp_product(0.0895386, phi2, 14);
0098 int phi = 24 + tmp;
0099
0100 int processor = track.sector();
0101 int HF = track.hasFineEta();
0102
0103 int quality = 0;
0104 if (useNewQualityCalculation_) {
0105 int r = rank(track);
0106 if (r < 192)
0107 quality = 12;
0108 else if (r < 204)
0109 quality = 13;
0110 else if (r < 220)
0111 quality = 14;
0112 else
0113 quality = 15;
0114 } else {
0115 quality = 12 | (rank(track) >> 6);
0116 }
0117
0118 int dxy = abs(track.dxy()) >> 8;
0119 if (dxy > 3)
0120 dxy = 3;
0121
0122 int trackAddr;
0123 std::map<int, int> addr = trackAddress(track, trackAddr);
0124
0125 l1t::RegionalMuonCand muon(pt, phi, eta, sign, signValid, quality, processor, l1t::bmtf, addr);
0126 muon.setHwHF(HF);
0127 muon.setHwPtUnconstrained(pt2);
0128 muon.setHwDXY(dxy);
0129
0130
0131 uint32_t word1 = pt;
0132 word1 = word1 | quality << 9;
0133 word1 = word1 | (twosCompToBits(eta)) << 13;
0134 word1 = word1 | HF << 22;
0135 word1 = word1 | (twosCompToBits(phi)) << 23;
0136
0137 uint32_t word2 = sign;
0138 word2 = word2 | signValid << 1;
0139 word2 = word2 | dxy << 2;
0140 word2 = word2 | trackAddr << 4;
0141 word2 = word2 | (twosCompToBits(track.wheel())) << 20;
0142 word2 = word2 | pt2 << 23;
0143 muon.setDataword(word2, word1);
0144 return muon;
0145 }
0146
0147 void L1TMuonBarrelKalmanAlgo::addBMTFMuon(int bx,
0148 const L1MuKBMTrack& track,
0149 std::unique_ptr<l1t::RegionalMuonCandBxCollection>& out) {
0150 out->push_back(bx, convertToBMTF(track));
0151 }
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 uint L1TMuonBarrelKalmanAlgo::matchAbs(std::map<uint, uint>& info, uint i, uint j) {
0176 if (info[i] < info[j])
0177 return i;
0178 else
0179 return j;
0180 }
0181
0182 std::pair<bool, uint> L1TMuonBarrelKalmanAlgo::match(const L1MuKBMTCombinedStubRef& seed,
0183 const L1MuKBMTCombinedStubRefVector& stubs,
0184 int step) {
0185 L1MuKBMTCombinedStubRefVector selected;
0186
0187 std::map<uint, uint> diffInfo;
0188 for (uint i = 0; i < 12; ++i) {
0189 diffInfo[i] = 60000;
0190 }
0191
0192 std::map<uint, uint> stubInfo;
0193
0194 int sector = seed->scNum();
0195 int previousSector = sector - 1;
0196 int nextSector = sector + 1;
0197 if (sector == 0) {
0198 previousSector = 11;
0199 }
0200 if (sector == 11) {
0201 nextSector = 0;
0202 }
0203
0204 int wheel = seed->whNum();
0205 int innerWheel = 0;
0206 if (wheel == -2)
0207 innerWheel = -1;
0208 if (wheel == -1)
0209 innerWheel = 0;
0210 if (wheel == 0)
0211 innerWheel = 1982;
0212 if (wheel == 1)
0213 innerWheel = 0;
0214 if (wheel == 2)
0215 innerWheel = 1;
0216
0217
0218 uint N = 0;
0219 for (const auto& stub : stubs) {
0220 N = N + 1;
0221
0222 if (stub->stNum() != step)
0223 continue;
0224
0225 uint distance =
0226 fabs(wrapAround(((correctedPhi(seed, seed->scNum()) - correctedPhi(stub, seed->scNum())) >> 3), 1024));
0227
0228 if (stub->scNum() == previousSector) {
0229 if (stub->whNum() == wheel) {
0230 if (!stub->tag()) {
0231 diffInfo[0] = distance;
0232 stubInfo[0] = N - 1;
0233 } else {
0234 diffInfo[1] = distance;
0235 stubInfo[1] = N - 1;
0236 }
0237 } else if (stub->whNum() == innerWheel) {
0238 if (!stub->tag()) {
0239 diffInfo[2] = distance;
0240 stubInfo[2] = N - 1;
0241 } else {
0242 diffInfo[3] = distance;
0243 stubInfo[3] = N - 1;
0244 }
0245 }
0246 } else if (stub->scNum() == sector) {
0247 if (stub->whNum() == wheel) {
0248 if (!stub->tag()) {
0249 diffInfo[4] = distance;
0250 stubInfo[4] = N - 1;
0251 } else {
0252 diffInfo[5] = distance;
0253 stubInfo[5] = N - 1;
0254 }
0255 } else if (stub->whNum() == innerWheel) {
0256 if (!stub->tag()) {
0257 diffInfo[6] = distance;
0258 stubInfo[6] = N - 1;
0259 } else {
0260 diffInfo[7] = distance;
0261 stubInfo[7] = N - 1;
0262 }
0263 }
0264 } else if (stub->scNum() == nextSector) {
0265 if (stub->whNum() == wheel) {
0266 if (!stub->tag()) {
0267 diffInfo[8] = distance;
0268 stubInfo[8] = N - 1;
0269 } else {
0270 diffInfo[9] = distance;
0271 stubInfo[9] = N - 1;
0272 }
0273 } else if (stub->whNum() == innerWheel) {
0274 if (!stub->tag()) {
0275 diffInfo[10] = distance;
0276 stubInfo[10] = N - 1;
0277 } else {
0278 diffInfo[11] = distance;
0279 stubInfo[11] = N - 1;
0280 }
0281 }
0282 }
0283 }
0284
0285 uint s1_1 = matchAbs(diffInfo, 0, 1);
0286 uint s1_2 = matchAbs(diffInfo, 2, 3);
0287 uint s1_3 = matchAbs(diffInfo, 4, 5);
0288 uint s1_4 = matchAbs(diffInfo, 6, 7);
0289 uint s1_5 = matchAbs(diffInfo, 8, 9);
0290 uint s1_6 = matchAbs(diffInfo, 10, 11);
0291
0292 uint s2_1 = matchAbs(diffInfo, s1_1, s1_2);
0293 uint s2_2 = matchAbs(diffInfo, s1_3, s1_4);
0294 uint s2_3 = matchAbs(diffInfo, s1_5, s1_6);
0295
0296 uint s3_1 = matchAbs(diffInfo, s2_1, s2_2);
0297
0298 uint s4 = matchAbs(diffInfo, s3_1, s2_3);
0299
0300 if (diffInfo[s4] != 60000)
0301 return std::make_pair(true, stubInfo[s4]);
0302 else
0303 return std::make_pair(false, 0);
0304 }
0305
0306 int L1TMuonBarrelKalmanAlgo::correctedPhiB(const L1MuKBMTCombinedStubRef& stub) {
0307
0308 return 8 * stub->phiB();
0309 }
0310
0311 int L1TMuonBarrelKalmanAlgo::correctedPhi(const L1MuKBMTCombinedStubRef& stub, int sector) {
0312 if (stub->scNum() == sector) {
0313 return stub->phi();
0314 } else if ((stub->scNum() == sector - 1) || (stub->scNum() == 11 && sector == 0)) {
0315 return stub->phi() - 2144;
0316 } else if ((stub->scNum() == sector + 1) || (stub->scNum() == 0 && sector == 11)) {
0317 return stub->phi() + 2144;
0318 }
0319 return stub->phi();
0320 }
0321
0322 int L1TMuonBarrelKalmanAlgo::hitPattern(const L1MuKBMTrack& track) {
0323 unsigned int mask = 0;
0324 for (const auto& stub : track.stubs()) {
0325 mask = mask + round(pow(2, stub->stNum() - 1));
0326 }
0327 return mask;
0328 }
0329
0330 int L1TMuonBarrelKalmanAlgo::customBitmask(unsigned int bit1, unsigned int bit2, unsigned int bit3, unsigned int bit4) {
0331 return bit1 * 1 + bit2 * 2 + bit3 * 4 + bit4 * 8;
0332 }
0333
0334 bool L1TMuonBarrelKalmanAlgo::getBit(int bitmask, int pos) { return (bitmask & (1 << pos)) >> pos; }
0335
0336 void L1TMuonBarrelKalmanAlgo::propagate(L1MuKBMTrack& track) {
0337 int K = track.curvature();
0338 int phi = track.positionAngle();
0339 int phiB = track.bendingAngle();
0340 unsigned int step = track.step();
0341
0342
0343
0344
0345
0346 int charge = 1;
0347 if (K != 0)
0348 charge = K / fabs(K);
0349
0350 int KBound = K;
0351
0352 if (KBound > 4095)
0353 KBound = 4095;
0354 if (KBound < -4095)
0355 KBound = -4095;
0356
0357 int deltaK = 0;
0358 int KNew = 0;
0359 if (step == 1) {
0360 int addr = KBound / 2;
0361 if (addr < 0)
0362 addr = (-KBound) / 2;
0363 deltaK = 2 * addr - int(2 * addr / (1 + eLoss_[step - 1] * addr));
0364
0365 if (verbose_)
0366 printf("propagate to vertex K=%d deltaK=%d addr=%d\n", K, deltaK, addr);
0367 }
0368
0369 if (K >= 0)
0370 KNew = K - deltaK;
0371 else
0372 KNew = K + deltaK;
0373
0374
0375 ap_fixed<BITSCURV, BITSCURV> phi11 = ap_fixed<BITSPARAM + 1, 2>(aPhi_[step - 1]) * ap_fixed<BITSCURV, BITSCURV>(K);
0376 ap_fixed<BITSPHIB, BITSPHIB> phi12 =
0377 ap_fixed<BITSPARAM + 1, 2>(-bPhi_[step - 1]) * ap_fixed<BITSPHIB, BITSPHIB>(phiB);
0378
0379 if (verbose_) {
0380 printf("phi prop = %d * %f = %d, %d * %f = %d\n",
0381 K,
0382 ap_fixed<BITSPARAM + 1, 2>(aPhi_[step - 1]).to_float(),
0383 phi11.to_int(),
0384 phiB,
0385 ap_fixed<BITSPARAM + 1, 2>(-bPhi_[step - 1]).to_float(),
0386 phi12.to_int());
0387 }
0388 int phiNew = ap_fixed<BITSPHI, BITSPHI>(phi + phi11 + phi12);
0389
0390
0391 ap_fixed<BITSCURV, BITSCURV> phiB11 = ap_fixed<BITSPARAM, 1>(aPhiB_[step - 1]) * ap_fixed<BITSCURV, BITSCURV>(K);
0392 ap_fixed<BITSPHIB + 1, BITSPHIB + 1> phiB12 =
0393 ap_ufixed<BITSPARAM + 1, 1>(bPhiB_[step - 1]) * ap_fixed<BITSPHIB, BITSPHIB>(phiB);
0394 int phiBNew = ap_fixed<13, 13>(phiB11 + phiB12);
0395 if (verbose_) {
0396 printf("phiB prop = %d * %f = %d, %d * %f = %d\n",
0397 K,
0398 ap_fixed<BITSPARAM + 1, 2>(aPhiB_[step - 1]).to_float(),
0399 phiB11.to_int(),
0400 phiB,
0401 ap_ufixed<BITSPARAM + 1, 1>(bPhiB_[step - 1]).to_float(),
0402 phiB12.to_int());
0403 }
0404
0405
0406 if (step == 1) {
0407 int addr = KBound / 2;
0408
0409 ap_ufixed<11, 11> dxyOffset = (int)fabs(aPhiB_[step - 1] * addr / (1 + charge * aPhiBNLO_[step - 1] * addr));
0410 ap_fixed<12, 12> DXY;
0411 if (addr > 0)
0412 DXY = -dxyOffset;
0413 else
0414 DXY = dxyOffset;
0415 phiBNew = ap_fixed<BITSPHIB, BITSPHIB>(DXY - ap_fixed<BITSPHIB, BITSPHIB>(phiB));
0416 if (verbose_) {
0417 printf("Vertex phiB prop = %d - %d = %d\n", DXY.to_int(), ap_fixed<BITSPHIB, BITSPHIB>(phiB).to_int(), phiBNew);
0418 }
0419 }
0420
0421
0422
0423
0424
0425 double a[9];
0426 a[0] = 1.;
0427 a[1] = 0.0;
0428 a[2] = 0.0;
0429 a[3] = aPhi_[step - 1];
0430
0431 a[4] = 1.0;
0432 a[5] = -bPhi_[step - 1];
0433
0434 a[6] = aPhiB_[step - 1];
0435 if (step == 1)
0436 a[6] = aPhiB_[step - 1] / 2.0;
0437
0438 a[7] = 0.0;
0439 a[8] = bPhiB_[step - 1];
0440
0441 ROOT::Math::SMatrix<double, 3> P(a, 9);
0442
0443 const std::vector<double>& covLine = track.covariance();
0444 L1MuKBMTrack::CovarianceMatrix cov(covLine.begin(), covLine.end());
0445 cov = ROOT::Math::Similarity(P, cov);
0446
0447
0448 double phiRMS = mScatteringPhi_[step - 1] * K * K;
0449 double phiBRMS = mScatteringPhiB_[step - 1] * K * K;
0450
0451 std::vector<double> b(6);
0452 b[0] = 0;
0453 b[1] = 0;
0454 b[2] = phiRMS;
0455 b[3] = 0;
0456 b[4] = 0;
0457 b[5] = phiBRMS;
0458
0459 reco::Candidate::CovarianceMatrix MS(b.begin(), b.end());
0460
0461 cov = cov + MS;
0462
0463 if (verbose_) {
0464 printf("Covariance term for phiB = %f\n", cov(2, 2));
0465 printf("Multiple scattering term for phiB = %f\n", MS(2, 2));
0466 }
0467
0468 track.setCovariance(cov);
0469 track.setCoordinates(step - 1, KNew, phiNew, phiBNew);
0470 }
0471
0472 bool L1TMuonBarrelKalmanAlgo::update(L1MuKBMTrack& track, const L1MuKBMTCombinedStubRef& stub, int mask, int seedQual) {
0473 updateEta(track, stub);
0474 if (useOfflineAlgo_) {
0475 if (mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12)
0476 return updateOffline(track, stub);
0477 else
0478 return updateOffline1D(track, stub);
0479
0480 } else
0481 return updateLUT(track, stub, mask, seedQual);
0482 }
0483
0484 bool L1TMuonBarrelKalmanAlgo::updateOffline(L1MuKBMTrack& track, const L1MuKBMTCombinedStubRef& stub) {
0485 int trackK = track.curvature();
0486 int trackPhi = track.positionAngle();
0487 int trackPhiB = track.bendingAngle();
0488
0489 int phi = correctedPhi(stub, track.sector());
0490 int phiB = correctedPhiB(stub);
0491
0492 Vector2 residual;
0493 residual[0] = phi - trackPhi;
0494 residual[1] = phiB - trackPhiB;
0495
0496 Matrix23 H;
0497 H(0, 0) = 0.0;
0498 H(0, 1) = 1.0;
0499 H(0, 2) = 0.0;
0500 H(1, 0) = 0.0;
0501 H(1, 1) = 0.0;
0502 H(1, 2) = 1.0;
0503
0504 CovarianceMatrix2 R;
0505 R(0, 0) = pointResolutionPhi_;
0506 R(0, 1) = 0.0;
0507 R(1, 0) = 0.0;
0508 if (stub->quality() < 4)
0509 R(1, 1) = pointResolutionPhiBL_[track.step() - 1];
0510 else
0511 R(1, 1) = pointResolutionPhiBH_[track.step() - 1];
0512
0513 const std::vector<double>& covLine = track.covariance();
0514 L1MuKBMTrack::CovarianceMatrix cov(covLine.begin(), covLine.end());
0515
0516 CovarianceMatrix2 S = ROOT::Math::Similarity(H, cov) + R;
0517 if (!S.Invert())
0518 return false;
0519 Matrix32 Gain = cov * ROOT::Math::Transpose(H) * S;
0520
0521 track.setKalmanGain(
0522 track.step(), fabs(trackK), Gain(0, 0), Gain(0, 1), Gain(1, 0), Gain(1, 1), Gain(2, 0), Gain(2, 1));
0523
0524 int KNew = (trackK + int(Gain(0, 0) * residual(0) + Gain(0, 1) * residual(1)));
0525 if (fabs(KNew) > 8192)
0526 return false;
0527
0528 int phiNew = wrapAround(trackPhi + residual(0), 8192);
0529 int phiBNew = wrapAround(trackPhiB + int(Gain(2, 0) * residual(0) + Gain(2, 1) * residual(1)), 4096);
0530
0531 track.setResidual(stub->stNum() - 1, fabs(phi - phiNew) + fabs(phiB - phiBNew) / 8);
0532
0533 if (verbose_) {
0534 printf("residual %d - %d = %d %d - %d = %d\n", phi, trackPhi, int(residual[0]), phiB, trackPhiB, int(residual[1]));
0535 printf("Gains offline: %f %f %f %f\n", Gain(0, 0), Gain(0, 1), Gain(2, 0), Gain(2, 1));
0536 printf(" K = %d + %f * %f + %f * %f\n", trackK, Gain(0, 0), residual(0), Gain(0, 1), residual(1));
0537 printf(" phiB = %d + %f * %f + %f * %f\n", trackPhiB, Gain(2, 0), residual(0), Gain(2, 1), residual(1));
0538 }
0539
0540 track.setCoordinates(track.step(), KNew, phiNew, phiBNew);
0541 Matrix33 covNew = cov - Gain * (H * cov);
0542 L1MuKBMTrack::CovarianceMatrix c;
0543
0544 c(0, 0) = covNew(0, 0);
0545 c(0, 1) = covNew(0, 1);
0546 c(0, 2) = covNew(0, 2);
0547 c(1, 0) = covNew(1, 0);
0548 c(1, 1) = covNew(1, 1);
0549 c(1, 2) = covNew(1, 2);
0550 c(2, 0) = covNew(2, 0);
0551 c(2, 1) = covNew(2, 1);
0552 c(2, 2) = covNew(2, 2);
0553 if (verbose_) {
0554 printf("Post Fit Covariance Matrix %f %f %f\n", cov(0, 0), cov(1, 1), cov(2, 2));
0555 }
0556
0557 track.setCovariance(c);
0558 track.addStub(stub);
0559 track.setHitPattern(hitPattern(track));
0560
0561 return true;
0562 }
0563
0564 bool L1TMuonBarrelKalmanAlgo::updateOffline1D(L1MuKBMTrack& track, const L1MuKBMTCombinedStubRef& stub) {
0565 int trackK = track.curvature();
0566 int trackPhi = track.positionAngle();
0567 int trackPhiB = track.bendingAngle();
0568
0569 int phi = correctedPhi(stub, track.sector());
0570
0571 double residual = phi - trackPhi;
0572
0573 if (verbose_)
0574 printf("residuals %d - %d = %d\n", phi, trackPhi, int(residual));
0575
0576 Matrix13 H;
0577 H(0, 0) = 0.0;
0578 H(0, 1) = 1.0;
0579 H(0, 2) = 0.0;
0580
0581 const std::vector<double>& covLine = track.covariance();
0582 L1MuKBMTrack::CovarianceMatrix cov(covLine.begin(), covLine.end());
0583
0584 double S = ROOT::Math::Similarity(H, cov)(0, 0) + pointResolutionPhi_;
0585
0586 if (S == 0.0)
0587 return false;
0588 Matrix31 Gain = cov * ROOT::Math::Transpose(H) / S;
0589
0590 track.setKalmanGain(track.step(), fabs(trackK), Gain(0, 0), 0.0, Gain(1, 0), 0.0, Gain(2, 0), 0.0);
0591 if (verbose_)
0592 printf("Gains: %f %f\n", Gain(0, 0), Gain(2, 0));
0593
0594 int KNew = wrapAround(trackK + int(Gain(0, 0) * residual), 8192);
0595 int phiNew = wrapAround(trackPhi + residual, 8192);
0596 int phiBNew = wrapAround(trackPhiB + int(Gain(2, 0) * residual), 4096);
0597 track.setCoordinates(track.step(), KNew, phiNew, phiBNew);
0598 Matrix33 covNew = cov - Gain * (H * cov);
0599 L1MuKBMTrack::CovarianceMatrix c;
0600
0601 if (verbose_) {
0602 printf("phiUpdate: %d %d\n", int(Gain(0, 0) * residual), int(Gain(2, 0) * residual));
0603 }
0604
0605 c(0, 0) = covNew(0, 0);
0606 c(0, 1) = covNew(0, 1);
0607 c(0, 2) = covNew(0, 2);
0608 c(1, 0) = covNew(1, 0);
0609 c(1, 1) = covNew(1, 1);
0610 c(1, 2) = covNew(1, 2);
0611 c(2, 0) = covNew(2, 0);
0612 c(2, 1) = covNew(2, 1);
0613 c(2, 2) = covNew(2, 2);
0614 track.setCovariance(c);
0615 track.addStub(stub);
0616 track.setHitPattern(hitPattern(track));
0617
0618 return true;
0619 }
0620
0621 bool L1TMuonBarrelKalmanAlgo::updateLUT(L1MuKBMTrack& track,
0622 const L1MuKBMTCombinedStubRef& stub,
0623 int mask,
0624 int seedQual) {
0625 int trackK = track.curvature();
0626 int trackPhi = track.positionAngle();
0627 int trackPhiB = track.bendingAngle();
0628
0629 int phi = correctedPhi(stub, track.sector());
0630 int phiB = correctedPhiB(stub);
0631
0632 Vector2 residual;
0633 ap_fixed<BITSPHI + 1, BITSPHI + 1> residualPhi = phi - trackPhi;
0634 ap_fixed<BITSPHIB + 1, BITSPHIB + 1> residualPhiB = phiB - trackPhiB;
0635
0636 if (verbose_)
0637 printf("residual %d - %d = %d %d - %d = %d\n",
0638 phi,
0639 trackPhi,
0640 residualPhi.to_int(),
0641 phiB,
0642 trackPhiB,
0643 residualPhiB.to_int());
0644
0645 uint absK = fabs(trackK);
0646 if (absK > 4095)
0647 absK = 4095;
0648
0649 std::vector<float> GAIN;
0650
0651 if (!(mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12)) {
0652 GAIN = lutService_->trackGain(track.step(), track.hitPattern(), absK / 4);
0653 GAIN[1] = 0.0;
0654 GAIN[3] = 0.0;
0655
0656 } else {
0657 GAIN = lutService_->trackGain2(track.step(), track.hitPattern(), absK / 8, seedQual, stub->quality());
0658 }
0659 if (verbose_) {
0660 printf("Gains (fp): %f %f %f %f\n", GAIN[0], GAIN[1], GAIN[2], GAIN[3]);
0661 if (!(mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12))
0662 printf("Addr=%d gain0=%f gain4=-%f\n",
0663 absK / 4,
0664 ap_ufixed<GAIN_0, GAIN_0INT>(GAIN[0]).to_float(),
0665 ap_ufixed<GAIN_4, GAIN_4INT>(GAIN[2]).to_float());
0666 else
0667 printf("Addr=%d %f -%f %f %f\n",
0668 absK / 4,
0669 ap_fixed<GAIN2_0, GAIN2_0INT>(GAIN[0]).to_float(),
0670 ap_ufixed<GAIN2_1, GAIN2_1INT>(GAIN[1]).to_float(),
0671 ap_ufixed<GAIN2_4, GAIN2_4INT>(GAIN[2]).to_float(),
0672 ap_ufixed<GAIN2_5, GAIN2_5INT>(GAIN[3]).to_float());
0673 }
0674
0675 track.setKalmanGain(track.step(), fabs(trackK), GAIN[0], GAIN[1], 1, 0, GAIN[2], GAIN[3]);
0676
0677 int KNew;
0678 if (!(mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12)) {
0679 KNew = ap_fixed<BITSPHI + 9, BITSPHI + 9>(ap_fixed<BITSCURV, BITSCURV>(trackK) +
0680 ap_ufixed<GAIN_0, GAIN_0INT>(GAIN[0]) * residualPhi);
0681 } else {
0682 ap_fixed<BITSPHI + 7, BITSPHI + 7> k11 = ap_fixed<GAIN2_0, GAIN2_0INT>(GAIN[0]) * residualPhi;
0683 ap_fixed<BITSPHIB + 4, BITSPHIB + 4> k12 = ap_ufixed<GAIN2_1, GAIN2_1INT>(GAIN[1]) * residualPhiB;
0684 KNew = ap_fixed<BITSPHI + 9, BITSPHI + 9>(ap_fixed<BITSCURV, BITSCURV>(trackK) + k11 - k12);
0685 }
0686 if (fabs(KNew) >= 8191)
0687 return false;
0688 KNew = wrapAround(KNew, 8192);
0689 int phiNew = phi;
0690
0691
0692 ap_fixed<BITSPHI + 5, BITSPHI + 5> pbdouble_0 = ap_ufixed<GAIN2_4, GAIN2_4INT>(GAIN[2]) * residualPhi;
0693 ap_fixed<BITSPHIB + 24, BITSPHIB + 4> pb_1 = ap_ufixed<GAIN2_5, GAIN2_5INT>(GAIN[3]) * residualPhiB;
0694 ap_fixed<BITSPHI + 9, BITSPHI + 5> pb_0 = ap_ufixed<GAIN_4, GAIN_4INT>(GAIN[2]) * residualPhi;
0695
0696 if (verbose_) {
0697 printf("phiupdate %f %f %f\n", pb_0.to_float(), pb_1.to_float(), pbdouble_0.to_float());
0698 }
0699
0700 int phiBNew;
0701 if (!(mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12)) {
0702 phiBNew = ap_fixed<BITSPHI + 8, BITSPHI + 8>(ap_fixed<BITSPHIB, BITSPHIB>(trackPhiB) -
0703 ap_ufixed<GAIN_4, GAIN_4INT>(GAIN[2]) * residualPhi);
0704
0705 if (fabs(phiBNew) >= 4095)
0706 return false;
0707 } else {
0708 phiBNew = ap_fixed<BITSPHI + 7, BITSPHI + 7>(ap_fixed<BITSPHIB, BITSPHIB>(trackPhiB) + pb_1 - pbdouble_0);
0709 if (fabs(phiBNew) >= 4095)
0710 return false;
0711 }
0712 track.setCoordinates(track.step(), KNew, phiNew, phiBNew);
0713 track.addStub(stub);
0714 track.setHitPattern(hitPattern(track));
0715 return true;
0716 }
0717
0718 void L1TMuonBarrelKalmanAlgo::updateEta(L1MuKBMTrack& track, const L1MuKBMTCombinedStubRef& stub) {}
0719
0720 void L1TMuonBarrelKalmanAlgo::vertexConstraint(L1MuKBMTrack& track) {
0721 if (useOfflineAlgo_)
0722 vertexConstraintOffline(track);
0723 else
0724 vertexConstraintLUT(track);
0725 }
0726
0727 void L1TMuonBarrelKalmanAlgo::vertexConstraintOffline(L1MuKBMTrack& track) {
0728 double residual = -track.dxy();
0729 Matrix13 H;
0730 H(0, 0) = 0;
0731 H(0, 1) = 0;
0732 H(0, 2) = 1;
0733
0734 const std::vector<double>& covLine = track.covariance();
0735 L1MuKBMTrack::CovarianceMatrix cov(covLine.begin(), covLine.end());
0736
0737 double S = (ROOT::Math::Similarity(H, cov))(0, 0) + pointResolutionVertex_;
0738 S = 1.0 / S;
0739 Matrix31 Gain = cov * (ROOT::Math::Transpose(H)) * S;
0740 track.setKalmanGain(track.step(), fabs(track.curvature()), Gain(0, 0), Gain(1, 0), Gain(2, 0));
0741
0742 if (verbose_) {
0743 printf("sigma3=%f sigma6=%f\n", cov(0, 3), cov(3, 3));
0744 printf(" K = %d + %f * %f\n", track.curvature(), Gain(0, 0), residual);
0745 }
0746
0747 int KNew = wrapAround(int(track.curvature() + Gain(0, 0) * residual), 8192);
0748 int phiNew = wrapAround(int(track.positionAngle() + Gain(1, 0) * residual), 8192);
0749 int dxyNew = wrapAround(int(track.dxy() + Gain(2, 0) * residual), 8192);
0750 if (verbose_)
0751 printf("Post fit impact parameter=%d\n", dxyNew);
0752 track.setCoordinatesAtVertex(KNew, phiNew, -residual);
0753 Matrix33 covNew = cov - Gain * (H * cov);
0754 L1MuKBMTrack::CovarianceMatrix c;
0755 c(0, 0) = covNew(0, 0);
0756 c(0, 1) = covNew(0, 1);
0757 c(0, 2) = covNew(0, 2);
0758 c(1, 0) = covNew(1, 0);
0759 c(1, 1) = covNew(1, 1);
0760 c(1, 2) = covNew(1, 2);
0761 c(2, 0) = covNew(2, 0);
0762 c(2, 1) = covNew(2, 1);
0763 c(2, 2) = covNew(2, 2);
0764 track.setCovariance(c);
0765
0766 }
0767
0768 void L1TMuonBarrelKalmanAlgo::vertexConstraintLUT(L1MuKBMTrack& track) {
0769 double residual = -track.dxy();
0770 uint absK = fabs(track.curvature());
0771 if (absK > 2047)
0772 absK = 2047;
0773
0774 std::pair<float, float> GAIN = lutService_->vertexGain(track.hitPattern(), absK / 2);
0775 track.setKalmanGain(track.step(), fabs(track.curvature()), GAIN.first, GAIN.second, -1);
0776
0777 ap_fixed<BITSCURV, BITSCURV> k_0 =
0778 -(ap_ufixed<GAIN_V0, GAIN_V0INT>(fabs(GAIN.first))) * ap_fixed<BITSPHIB, BITSPHIB>(residual);
0779 int KNew = ap_fixed<BITSCURV, BITSCURV>(k_0 + ap_fixed<BITSCURV, BITSCURV>(track.curvature()));
0780
0781 if (verbose_) {
0782 printf("VERTEX GAIN(%d)= -%f * %d = %d\n",
0783 absK / 2,
0784 ap_ufixed<GAIN_V0, GAIN_V0INT>(fabs(GAIN.first)).to_float(),
0785 ap_fixed<BITSPHIB, BITSPHIB>(residual).to_int(),
0786 k_0.to_int());
0787 }
0788
0789 int p_0 = fp_product(GAIN.second, int(residual), 7);
0790 int phiNew = wrapAround(track.positionAngle() + p_0, 8192);
0791 track.setCoordinatesAtVertex(KNew, phiNew, -residual);
0792 }
0793
0794 void L1TMuonBarrelKalmanAlgo::setFloatingPointValues(L1MuKBMTrack& track, bool vertex) {
0795 int K, etaINT;
0796
0797 if (track.hasFineEta())
0798 etaINT = track.fineEta();
0799 else
0800 etaINT = track.coarseEta();
0801
0802 double lsb = 1.25 / float(1 << 13);
0803 double lsbEta = 0.010875;
0804
0805 if (vertex) {
0806 int charge = 1;
0807 if (track.curvatureAtVertex() < 0)
0808 charge = -1;
0809 double pt = double(ptLUT(track.curvatureAtVertex())) / 2.0;
0810
0811 double phi = track.sector() * M_PI / 6.0 + track.phiAtVertex() * M_PI / (6 * 2048.) - 2 * M_PI;
0812
0813 double eta = etaINT * lsbEta;
0814 track.setPtEtaPhi(pt, eta, phi);
0815 track.setCharge(charge);
0816 } else {
0817 K = track.curvatureAtMuon();
0818 if (K == 0)
0819 K = 1;
0820
0821 if (fabs(K) < 46)
0822 K = 46 * K / fabs(K);
0823 double pt = 1.0 / (lsb * fabs(K));
0824 if (pt < 1.6)
0825 pt = 1.6;
0826 track.setPtUnconstrained(pt);
0827 }
0828 }
0829
0830 std::pair<bool, L1MuKBMTrack> L1TMuonBarrelKalmanAlgo::chain(const L1MuKBMTCombinedStubRef& seed,
0831 const L1MuKBMTCombinedStubRefVector& stubs) {
0832 L1MuKBMTrackCollection pretracks;
0833 std::vector<int> combinatorics;
0834 int seedQual;
0835 switch (seed->stNum()) {
0836 case 1:
0837 combinatorics = combos1_;
0838 break;
0839 case 2:
0840 combinatorics = combos2_;
0841 break;
0842
0843 case 3:
0844 combinatorics = combos3_;
0845 break;
0846
0847 case 4:
0848 combinatorics = combos4_;
0849 break;
0850
0851 default:
0852 printf("Something really bad happend\n");
0853 }
0854
0855 L1MuKBMTrack nullTrack(seed, correctedPhi(seed, seed->scNum()), correctedPhiB(seed));
0856 seedQual = seed->quality();
0857 for (const auto& mask : combinatorics) {
0858 L1MuKBMTrack track(seed, correctedPhi(seed, seed->scNum()), correctedPhiB(seed));
0859 int phiB = correctedPhiB(seed);
0860 int charge;
0861 if (phiB == 0)
0862 charge = 0;
0863 else
0864 charge = phiB / fabs(phiB);
0865
0866 int address = phiB;
0867 if (track.step() == 4 && (fabs(seed->phiB()) > 15))
0868 address = charge * 15 * 8;
0869
0870 if (track.step() == 3 && (fabs(seed->phiB()) > 30))
0871 address = charge * 30 * 8;
0872 if (track.step() == 2 && (fabs(seed->phiB()) > 127))
0873 address = charge * 127 * 8;
0874 int initialK = int(initK_[seed->stNum() - 1] * address / (1 + initK2_[seed->stNum() - 1] * charge * address));
0875 if (initialK > 8191)
0876 initialK = 8191;
0877 if (initialK < -8191)
0878 initialK = -8191;
0879
0880 track.setCoordinates(seed->stNum(), initialK, correctedPhi(seed, seed->scNum()), phiB);
0881 if (seed->quality() < 4) {
0882 track.setCoordinates(seed->stNum(), 0, correctedPhi(seed, seed->scNum()), 0);
0883 }
0884
0885 track.setHitPattern(hitPattern(track));
0886
0887 L1MuKBMTrack::CovarianceMatrix covariance;
0888
0889 float DK = 512 * 512.;
0890 covariance(0, 0) = DK;
0891 covariance(0, 1) = 0;
0892 covariance(0, 2) = 0;
0893 covariance(1, 0) = 0;
0894 covariance(1, 1) = float(pointResolutionPhi_);
0895 covariance(1, 2) = 0;
0896 covariance(2, 0) = 0;
0897 covariance(2, 1) = 0;
0898 if (!(mask == 3 || mask == 5 || mask == 9 || mask == 6 || mask == 10 || mask == 12))
0899 covariance(2, 2) = float(pointResolutionPhiB_);
0900 else {
0901 if (seed->quality() < 4)
0902 covariance(2, 2) = float(pointResolutionPhiBL_[seed->stNum() - 1]);
0903 else
0904 covariance(2, 2) = float(pointResolutionPhiBH_[seed->stNum() - 1]);
0905 }
0906 track.setCovariance(covariance);
0907
0908
0909 if (verbose_) {
0910 printf("New Kalman fit staring at step=%d, phi=%d,phiB=%d with curvature=%d\n",
0911 track.step(),
0912 track.positionAngle(),
0913 track.bendingAngle(),
0914 track.curvature());
0915 printf("BITMASK:");
0916 for (unsigned int i = 0; i < 4; ++i)
0917 printf("%d", getBit(mask, i));
0918 printf("\n");
0919 printf("------------------------------------------------------\n");
0920 printf("------------------------------------------------------\n");
0921 printf("------------------------------------------------------\n");
0922 printf("stubs:\n");
0923 for (const auto& stub : stubs)
0924 printf("station=%d phi=%d phiB=%d qual=%d tag=%d sector=%d wheel=%d fineEta= %d %d\n",
0925 stub->stNum(),
0926 correctedPhi(stub, seed->scNum()),
0927 correctedPhiB(stub),
0928 stub->quality(),
0929 stub->tag(),
0930 stub->scNum(),
0931 stub->whNum(),
0932 stub->eta1(),
0933 stub->eta2());
0934 printf("------------------------------------------------------\n");
0935 printf("------------------------------------------------------\n");
0936 }
0937
0938 int phiAtStation2 = 0;
0939
0940 while (track.step() > 0) {
0941
0942 if (track.step() == 1) {
0943 track.setCoordinatesAtMuon(track.curvature(), track.positionAngle(), track.bendingAngle());
0944 phiAtStation2 = phiAt2(track);
0945 bool passed = estimateChiSquare(track);
0946 if (!passed)
0947 break;
0948 calculateEta(track);
0949 setFloatingPointValues(track, false);
0950
0951
0952
0953 if (verbose_)
0954 printf("Unconstrained PT in Muon System: pt=%f\n", track.ptUnconstrained());
0955 }
0956
0957 propagate(track);
0958 if (verbose_)
0959 printf("propagated Coordinates step:%d,phi=%d,phiB=%d,K=%d\n",
0960 track.step(),
0961 track.positionAngle(),
0962 track.bendingAngle(),
0963 track.curvature());
0964
0965 if (track.step() > 0)
0966 if (getBit(mask, track.step() - 1)) {
0967 std::pair<bool, uint> bestStub = match(seed, stubs, track.step());
0968 if ((!bestStub.first) || (!update(track, stubs[bestStub.second], mask, seedQual)))
0969 break;
0970 if (verbose_) {
0971 printf("updated Coordinates step:%d,phi=%d,phiB=%d,K=%d\n",
0972 track.step(),
0973 track.positionAngle(),
0974 track.bendingAngle(),
0975 track.curvature());
0976 }
0977 }
0978
0979 if (track.step() == 0) {
0980 track.setCoordinatesAtVertex(track.curvature(), track.positionAngle(), track.bendingAngle());
0981 if (verbose_)
0982 printf(" Coordinates before vertex constraint step:%d,phi=%d,dxy=%d,K=%d\n",
0983 track.step(),
0984 track.phiAtVertex(),
0985 track.dxy(),
0986 track.curvatureAtVertex());
0987 if (verbose_)
0988 printf("Chi Square = %d\n", track.approxChi2());
0989
0990 vertexConstraint(track);
0991 estimateCompatibility(track);
0992 if (verbose_) {
0993 printf(" Coordinates after vertex constraint step:%d,phi=%d,dxy=%d,K=%d maximum local chi2=%d\n",
0994 track.step(),
0995 track.phiAtVertex(),
0996 track.dxy(),
0997 track.curvatureAtVertex(),
0998 track.approxChi2());
0999 printf("------------------------------------------------------\n");
1000 printf("------------------------------------------------------\n");
1001 }
1002 setFloatingPointValues(track, true);
1003
1004 track.setCoordinatesAtMuon(track.curvatureAtMuon(), phiAtStation2, track.phiBAtMuon());
1005 track.setRank(rank(track));
1006 if (verbose_)
1007 printf("Floating point coordinates at vertex: pt=%f, eta=%f phi=%f\n", track.pt(), track.eta(), track.phi());
1008 pretracks.push_back(track);
1009 }
1010 }
1011 }
1012
1013
1014 L1MuKBMTrackCollection cleaned = clean(pretracks, seed->stNum());
1015
1016 if (!cleaned.empty()) {
1017 return std::make_pair(true, cleaned[0]);
1018 }
1019 return std::make_pair(false, nullTrack);
1020 }
1021
1022 bool L1TMuonBarrelKalmanAlgo::estimateChiSquare(L1MuKBMTrack& track) {
1023
1024
1025 int K = track.curvatureAtMuon();
1026
1027 uint chi = 0;
1028
1029
1030
1031
1032 int coords = wrapAround((track.phiAtMuon() + track.phiBAtMuon()) >> 4, 512);
1033 for (const auto& stub : track.stubs()) {
1034 int AK = wrapAround(fp_product(-chiSquare_[stub->stNum() - 1], K >> 4, 8), 256);
1035 int stubCoords = wrapAround((correctedPhi(stub, track.sector()) >> 4) + (stub->phiB() >> 1), 512);
1036 int diff1 = wrapAround(stubCoords - coords, 1024);
1037 uint delta = wrapAround(abs(diff1 + AK), 2048);
1038 chi = chi + delta;
1039 if (verbose_)
1040 printf("Chi Square stub for track with pattern=%d coords=%d -> AK=%d stubCoords=%d diff=%d delta=%d\n",
1041 track.hitPattern(),
1042 coords,
1043 AK,
1044 stubCoords,
1045 diff1,
1046 delta);
1047 }
1048
1049 if (chi > 127)
1050 chi = 127;
1051
1052
1053
1054
1055
1056
1057
1058
1059 track.setApproxChi2(chi);
1060 for (uint i = 0; i < chiSquareCutPattern_.size(); ++i) {
1061 if (track.hitPattern() == chiSquareCutPattern_[i] && fabs(K) < chiSquareCutCurv_[i] &&
1062 track.approxChi2() > chiSquareCut_[i])
1063 return false;
1064 }
1065 return true;
1066 }
1067
1068 void L1TMuonBarrelKalmanAlgo::estimateCompatibility(L1MuKBMTrack& track) {
1069 int K = track.curvatureAtVertex() >> 4;
1070
1071 if (track.stubs().size() != 2) {
1072 track.setTrackCompatibility(0);
1073 return;
1074 }
1075
1076 uint stubSel = 1;
1077 if (track.stubs()[0]->quality() > track.stubs()[1]->quality())
1078 stubSel = 0;
1079 const L1MuKBMTCombinedStubRef& stub = track.stubs()[stubSel];
1080
1081 if (verbose_) {
1082 printf("stubsel %d phi=%d phiB=%d\n", stubSel, stub->phi(), stub->phiB());
1083 }
1084
1085 ap_ufixed<BITSCURV - 5, BITSCURV - 5> absK;
1086 if (K < 0)
1087 absK = -K;
1088 else
1089 absK = K;
1090
1091 ap_fixed<12, 12> diff = ap_int<10>(stub->phiB()) -
1092 ap_ufixed<5, 1>(trackComp_[stub->stNum() - 1]) * ap_fixed<BITSCURV - 4, BITSCURV - 4>(K);
1093 ap_ufixed<11, 11> delta;
1094 if (diff.is_neg())
1095 delta = -diff;
1096 else
1097 delta = diff;
1098
1099 ap_ufixed<BITSCURV - 5, BITSCURV - 5> err =
1100 ap_uint<3>(trackCompErr1_[stub->stNum() - 1]) + ap_ufixed<5, 0>(trackCompErr2_[stub->stNum() - 1]) * absK;
1101 track.setTrackCompatibility(((int)delta) / ((int)err));
1102 for (uint i = 0; i < trackCompPattern_.size(); ++i) {
1103 int deltaMax = ap_ufixed<BITSCURV, BITSCURV>(err * trackCompCut_[i]);
1104 if (verbose_) {
1105 if (track.hitPattern() == trackCompPattern_[i]) {
1106 printf("delta = %d = abs(%d - %f*%d\n", delta.to_int(), stub->phiB(), trackComp_[stub->stNum() - 1], K);
1107 printf("err = %d = %f + %f*%d\n",
1108 err.to_int(),
1109 trackCompErr1_[stub->stNum() - 1],
1110 trackCompErr2_[stub->stNum() - 1],
1111 absK.to_int());
1112 printf("deltaMax = %d = %d*%d\n", deltaMax, err.to_int(), trackCompCut_[i]);
1113 }
1114 }
1115 if ((track.hitPattern() == trackCompPattern_[i]) && ((int)absK < trackCompCutCurv_[i]) &&
1116 ((track.approxChi2() > chiSquareCutTight_[i]) || (delta > deltaMax))) {
1117 track.setCoordinatesAtVertex(8191, track.phiAtVertex(), track.dxy());
1118 break;
1119 }
1120 }
1121 }
1122
1123 int L1TMuonBarrelKalmanAlgo::rank(const L1MuKBMTrack& track) {
1124
1125 uint chi = track.approxChi2() > 127 ? 127 : track.approxChi2();
1126 if (hitPattern(track) == customBitmask(0, 0, 1, 1)) {
1127 return 60;
1128 }
1129
1130 return 160 + (track.stubs().size()) * 20 - chi;
1131 }
1132
1133 int L1TMuonBarrelKalmanAlgo::wrapAround(int value, int maximum) {
1134 if (value > maximum - 1)
1135 return wrapAround(value - 2 * maximum, maximum);
1136 if (value < -maximum)
1137 return wrapAround(value + 2 * maximum, maximum);
1138 return value;
1139 }
1140
1141 int L1TMuonBarrelKalmanAlgo::encode(bool ownwheel, int sector, bool tag) {
1142 if (ownwheel) {
1143 if (sector == 0) {
1144 if (tag)
1145 return 9;
1146 else
1147 return 8;
1148 } else if (sector == 1) {
1149 if (tag)
1150 return 11;
1151 else
1152 return 10;
1153
1154 } else {
1155 if (tag)
1156 return 13;
1157 else
1158 return 12;
1159 }
1160
1161 } else {
1162 if (sector == 0) {
1163 if (tag)
1164 return 1;
1165 else
1166 return 0;
1167 } else if (sector == 1) {
1168 if (tag)
1169 return 3;
1170 else
1171 return 2;
1172
1173 } else {
1174 if (tag)
1175 return 5;
1176 else
1177 return 4;
1178 }
1179 }
1180 return 15;
1181 }
1182
1183 std::map<int, int> L1TMuonBarrelKalmanAlgo::trackAddress(const L1MuKBMTrack& track, int& word) {
1184 std::map<int, int> out;
1185
1186 out[l1t::RegionalMuonCand::kWheelSide] = track.wheel() < 0;
1187 if (track.wheel() == -2)
1188 out[l1t::RegionalMuonCand::kWheelNum] = 2;
1189 else if (track.wheel() == -1)
1190 out[l1t::RegionalMuonCand::kWheelNum] = 1;
1191 else if (track.wheel() == 0)
1192 out[l1t::RegionalMuonCand::kWheelNum] = 0;
1193 else if (track.wheel() == 1)
1194 out[l1t::RegionalMuonCand::kWheelNum] = 1;
1195 else if (track.wheel() == 2)
1196 out[l1t::RegionalMuonCand::kWheelNum] = 2;
1197 else
1198 out[l1t::RegionalMuonCand::kWheelNum] = 0;
1199 out[l1t::RegionalMuonCand::kStat1] = 15;
1200 out[l1t::RegionalMuonCand::kStat2] = 15;
1201 out[l1t::RegionalMuonCand::kStat3] = 15;
1202 out[l1t::RegionalMuonCand::kStat4] = 3;
1203 out[l1t::RegionalMuonCand::kSegSelStat1] = 0;
1204 out[l1t::RegionalMuonCand::kSegSelStat2] = 0;
1205 out[l1t::RegionalMuonCand::kSegSelStat3] = 0;
1206 out[l1t::RegionalMuonCand::kSegSelStat4] = 0;
1207
1208
1209 for (const auto& stub : track.stubs()) {
1210 bool ownwheel = stub->whNum() == track.wheel();
1211 int sector = 0;
1212 if ((stub->scNum() == track.sector() + 1) || (stub->scNum() == 0 && track.sector() == 11))
1213 sector = +1;
1214 if ((stub->scNum() == track.sector() - 1) || (stub->scNum() == 11 && track.sector() == 0))
1215 sector = -1;
1216 int addr = encode(ownwheel, sector, stub->tag());
1217
1218 if (stub->stNum() == 4) {
1219 if (stub->tag())
1220 addr = 1;
1221 else
1222 addr = 2;
1223 out[l1t::RegionalMuonCand::kStat4] = addr;
1224 }
1225 if (stub->stNum() == 3) {
1226 out[l1t::RegionalMuonCand::kStat3] = addr;
1227 }
1228 if (stub->stNum() == 2) {
1229 out[l1t::RegionalMuonCand::kStat2] = addr;
1230 }
1231 if (stub->stNum() == 1) {
1232 out[l1t::RegionalMuonCand::kStat1] = addr;
1233 }
1234 }
1235
1236 word = 0;
1237 word = word | out[l1t::RegionalMuonCand::kStat4] << 12;
1238 word = word | out[l1t::RegionalMuonCand::kStat3] << 8;
1239 word = word | out[l1t::RegionalMuonCand::kStat2] << 4;
1240 word = word | out[l1t::RegionalMuonCand::kStat1];
1241
1242 return out;
1243 }
1244
1245 uint L1TMuonBarrelKalmanAlgo::twosCompToBits(int q) {
1246 if (q >= 0)
1247 return q;
1248 else
1249 return (~q) + 1;
1250 }
1251
1252 int L1TMuonBarrelKalmanAlgo::fp_product(float a, int b, uint bits) {
1253
1254 return (long((a * (1 << bits)) * b)) >> bits;
1255 }
1256
1257 int L1TMuonBarrelKalmanAlgo::ptLUT(int K) {
1258 int charge = (K >= 0) ? +1 : -1;
1259 float lsb = 1.25 / float(1 << 13);
1260 float FK = fabs(K);
1261
1262 if (FK > 2047)
1263 FK = 2047.;
1264 if (FK < 26)
1265 FK = 26.;
1266
1267 FK = FK * lsb;
1268
1269
1270 FK = .8569 * FK / (1.0 + 0.1144 * FK);
1271
1272 FK = FK - charge * 1.23e-03;
1273
1274 FK = FK / 1.17;
1275
1276 int pt = 0;
1277 if (FK != 0)
1278 pt = int(2.0 / FK);
1279
1280 if (pt > 511)
1281 pt = 511;
1282
1283 if (pt < 8)
1284 pt = 8;
1285
1286 return pt;
1287 }
1288
1289 L1MuKBMTrackCollection L1TMuonBarrelKalmanAlgo::clean(const L1MuKBMTrackCollection& tracks, uint seed) {
1290 L1MuKBMTrackCollection out;
1291
1292 std::map<uint, int> infoRank;
1293 std::map<uint, L1MuKBMTrack> infoTrack;
1294 for (uint i = 3; i <= 15; ++i) {
1295 if (i == 4 || i == 8)
1296 continue;
1297 infoRank[i] = -1;
1298 }
1299
1300 for (const auto& track : tracks) {
1301 infoRank[track.hitPattern()] = rank(track);
1302 infoTrack[track.hitPattern()] = track;
1303 }
1304
1305 int selected = 15;
1306 if (seed == 4)
1307 {
1308 int sel6 = infoRank[10] >= infoRank[12] ? 10 : 12;
1309 int sel5 = infoRank[14] >= infoRank[9] ? 14 : 9;
1310 int sel4 = infoRank[11] >= infoRank[13] ? 11 : 13;
1311 int sel3 = infoRank[sel6] >= infoRank[sel5] ? sel6 : sel5;
1312 int sel2 = infoRank[sel4] >= infoRank[sel3] ? sel4 : sel3;
1313 selected = infoRank[15] >= infoRank[sel2] ? 15 : sel2;
1314 }
1315 if (seed == 3)
1316 {
1317 int sel2 = infoRank[5] >= infoRank[6] ? 5 : 6;
1318 selected = infoRank[7] >= infoRank[sel2] ? 7 : sel2;
1319 }
1320 if (seed == 2)
1321 selected = 3;
1322
1323 auto search = infoTrack.find(selected);
1324 if (search != infoTrack.end())
1325 out.push_back(search->second);
1326
1327 return out;
1328 }
1329
1330 uint L1TMuonBarrelKalmanAlgo::etaStubRank(const L1MuKBMTCombinedStubRef& stub) {
1331 if (stub->qeta1() != 0 && stub->qeta2() != 0) {
1332 return 0;
1333 }
1334 if (stub->qeta1() == 0) {
1335 return 0;
1336 }
1337
1338 return (stub->qeta1());
1339 }
1340
1341 void L1TMuonBarrelKalmanAlgo::calculateEta(L1MuKBMTrack& track) {
1342 uint pattern = track.hitPattern();
1343 int wheel = track.stubs()[0]->whNum();
1344 uint awheel = fabs(wheel);
1345 int sign = 1;
1346 if (wheel < 0)
1347 sign = -1;
1348 uint nstubs = track.stubs().size();
1349 uint mask = 0;
1350 for (unsigned int i = 0; i < track.stubs().size(); ++i) {
1351 if (fabs(track.stubs()[i]->whNum()) != awheel)
1352 mask = mask | (1 << i);
1353 }
1354 mask = (awheel << nstubs) | mask;
1355 track.setCoarseEta(sign * lutService_->coarseEta(pattern, mask));
1356 int sumweights = 0;
1357 int sums = 0;
1358
1359 for (const auto& stub : track.stubs()) {
1360 uint rank = etaStubRank(stub);
1361 if (rank == 0)
1362 continue;
1363
1364 sumweights += rank;
1365 sums += rank * stub->eta1();
1366 }
1367
1368 float factor;
1369 if (sumweights == 1)
1370 factor = 1.0;
1371 else if (sumweights == 2)
1372 factor = 0.5;
1373 else if (sumweights == 3)
1374 factor = 0.332031;
1375 else if (sumweights == 4)
1376 factor = 0.25;
1377 else if (sumweights == 5)
1378 factor = 0.199219;
1379 else if (sumweights == 6)
1380 factor = 0.164063;
1381 else
1382 factor = 0.0;
1383
1384 int eta = 0;
1385 if (sums > 0)
1386 eta = fp_product(factor, sums, 10);
1387 else
1388 eta = -fp_product(factor, fabs(sums), 10);
1389
1390
1391
1392
1393 if (sumweights > 0)
1394 track.setFineEta(eta);
1395 }
1396
1397 int L1TMuonBarrelKalmanAlgo::phiAt2(const L1MuKBMTrack& track) {
1398
1399 for (const auto& stub : track.stubs())
1400 if (stub->stNum() == 2)
1401 return correctedPhi(stub, track.sector());
1402
1403 ap_fixed<BITSPHI, BITSPHI> phi = track.phiAtMuon();
1404 ap_fixed<BITSPHIB, BITSPHIB> phiB = track.phiBAtMuon();
1405 ap_fixed<BITSPARAM, 1> phiAt2 = phiAt2_;
1406 int phiNew = ap_fixed<BITSPHI + 1, BITSPHI + 1, AP_TRN_ZERO, AP_SAT>(phi + phiAt2 * phiB);
1407
1408 if (verbose_)
1409 printf("Phi at second station=%d\n", phiNew);
1410 return phiNew;
1411 }