Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:22:02

0001 #include "L1Trigger/TrackFindingTracklet/interface/Tracklet.h"
0002 #include "L1Trigger/TrackFindingTracklet/interface/Settings.h"
0003 #include "L1Trigger/TrackFindingTracklet/interface/Stub.h"
0004 #include "L1Trigger/TrackFindingTracklet/interface/Track.h"
0005 
0006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0007 #include "FWCore/Utilities/interface/Exception.h"
0008 
0009 #include <memory>
0010 
0011 #include <sstream>
0012 
0013 using namespace std;
0014 using namespace trklet;
0015 
0016 Tracklet::Tracklet(Settings const& settings,
0017                    unsigned int iSeed,
0018                    const Stub* innerFPGAStub,
0019                    const Stub* middleFPGAStub,
0020                    const Stub* outerFPGAStub,
0021                    double rinv,
0022                    double phi0,
0023                    double d0,
0024                    double z0,
0025                    double t,
0026                    double rinvapprox,
0027                    double phi0approx,
0028                    double d0approx,
0029                    double z0approx,
0030                    double tapprox,
0031                    int irinv,
0032                    int iphi0,
0033                    int id0,
0034                    int iz0,
0035                    int it,
0036                    Projection projs[N_LAYER + N_DISK],
0037                    bool disk,
0038                    bool overlap)
0039     : settings_(settings) {
0040   seedIndex_ = iSeed;
0041 
0042   overlap_ = overlap;
0043   disk_ = disk;
0044   assert(!(disk && overlap));
0045   barrel_ = (!disk) && (!overlap);
0046   triplet_ = false;
0047 
0048   trackletIndex_ = -1;
0049   TCIndex_ = -1;
0050 
0051   assert(disk_ || barrel_ || overlap_);
0052 
0053   if (barrel_ && middleFPGAStub == nullptr)
0054     assert(innerFPGAStub->l1tstub()->layer() < N_LAYER);
0055 
0056   innerFPGAStub_ = innerFPGAStub;
0057   middleFPGAStub_ = middleFPGAStub;
0058   outerFPGAStub_ = outerFPGAStub;
0059 
0060   trackpars_.init(rinv, phi0, d0, t, z0);
0061 
0062   trackparsapprox_.init(rinvapprox, phi0approx, d0approx, tapprox, z0approx);
0063 
0064   fpgapars_.rinv().set(irinv, settings_.nbitsrinv(), false, __LINE__, __FILE__);
0065   fpgapars_.phi0().set(iphi0, settings_.nbitsphi0(), false, __LINE__, __FILE__);
0066   fpgapars_.d0().set(id0, settings_.nbitsd0(), false, __LINE__, __FILE__);
0067   fpgapars_.z0().set(iz0, settings_.nbitsz0(), false, __LINE__, __FILE__);
0068   fpgapars_.t().set(it, settings_.nbitst(), false, __LINE__, __FILE__);
0069 
0070   fpgatrack_ = nullptr;
0071 
0072   triplet_ = (seedIndex_ >= 8);
0073 
0074   //fill projection layers
0075   for (unsigned int i = 0; i < N_LAYER - 2; i++) {
0076     projlayer_[i] = settings.projlayers(seedIndex_, i);
0077   }
0078 
0079   //fill projection disks
0080   for (unsigned int i = 0; i < N_DISK; i++) {
0081     projdisk_[i] = settings.projdisks(seedIndex_, i);
0082   }
0083 
0084   //Handle projections to the layers
0085   for (unsigned int i = 0; i < N_LAYER - 2; i++) {
0086     if (projlayer_[i] == 0)
0087       continue;
0088     if (!projs[projlayer_[i] - 1].valid())
0089       continue;
0090 
0091     proj_[projlayer_[i] - 1] = projs[projlayer_[i] - 1];
0092   }
0093   //Now handle projections to the disks
0094   for (unsigned int i = 0; i < N_DISK; i++) {
0095     if (projdisk_[i] == 0)
0096       continue;
0097     if (!projs[N_LAYER + projdisk_[i] - 1].valid())
0098       continue;
0099 
0100     proj_[N_LAYER + projdisk_[i] - 1] = projs[N_LAYER + projdisk_[i] - 1];
0101   }
0102 
0103   ichisqrphifit_.set(-1, 8, false);
0104   ichisqrzfit_.set(-1, 8, false);
0105 }
0106 
0107 int Tracklet::tpseed() {
0108   set<int> tpset;
0109 
0110   set<int> tpsetstubinner;
0111   set<int> tpsetstubouter;
0112 
0113   vector<int> tps = innerFPGAStub_->l1tstub()->tps();
0114   for (auto tp : tps) {
0115     if (tp != 0) {
0116       tpsetstubinner.insert(tp);
0117       tpset.insert(abs(tp));
0118     }
0119   }
0120 
0121   tps = outerFPGAStub_->l1tstub()->tps();
0122   for (auto tp : tps) {
0123     if (tp != 0) {
0124       tpsetstubouter.insert(tp);
0125       tpset.insert(abs(tp));
0126     }
0127   }
0128 
0129   for (auto& tp : tpset) {
0130     if (tpsetstubinner.find(tp) != tpsetstubinner.end() && tpsetstubinner.find(-tp) != tpsetstubinner.end() &&
0131         tpsetstubouter.find(tp) != tpsetstubouter.end() && tpsetstubouter.find(-tp) != tpsetstubouter.end()) {
0132       return tp;
0133     }
0134   }
0135   return 0;
0136 }
0137 
0138 bool Tracklet::stubtruthmatch(const L1TStub* stub) {
0139   set<int> tpset;
0140   set<int> tpsetstub;
0141   set<int> tpsetstubinner;
0142   set<int> tpsetstubouter;
0143 
0144   vector<int> tps = stub->tps();
0145   for (auto tp : tps) {
0146     if (tp != 0) {
0147       tpsetstub.insert(tp);
0148       tpset.insert(abs(tp));
0149     }
0150   }
0151   tps = innerFPGAStub_->l1tstub()->tps();
0152   for (auto tp : tps) {
0153     if (tp != 0) {
0154       tpsetstubinner.insert(tp);
0155       tpset.insert(abs(tp));
0156     }
0157   }
0158   tps = outerFPGAStub_->l1tstub()->tps();
0159   for (auto tp : tps) {
0160     if (tp != 0) {
0161       tpsetstubouter.insert(tp);
0162       tpset.insert(abs(tp));
0163     }
0164   }
0165 
0166   for (auto tp : tpset) {
0167     if (tpsetstub.find(tp) != tpsetstub.end() && tpsetstub.find(-tp) != tpsetstub.end() &&
0168         tpsetstubinner.find(tp) != tpsetstubinner.end() && tpsetstubinner.find(-tp) != tpsetstubinner.end() &&
0169         tpsetstubouter.find(tp) != tpsetstubouter.end() && tpsetstubouter.find(-tp) != tpsetstubouter.end()) {
0170       return true;
0171     }
0172   }
0173 
0174   return false;
0175 }
0176 
0177 std::string Tracklet::addressstr() {
0178   std::string str;
0179   str = innerFPGAStub_->phiregionaddressstr() + "|";
0180   if (middleFPGAStub_) {
0181     str += middleFPGAStub_->phiregionaddressstr() + "|";
0182   }
0183   str += outerFPGAStub_->phiregionaddressstr();
0184 
0185   return str;
0186 }
0187 
0188 std::string Tracklet::trackletparstr() {
0189   if (settings_.writeoutReal()) {
0190     std::string oss = std::to_string(fpgapars_.rinv().value() * settings_.krinvpars()) + " " +
0191                       std::to_string(fpgapars_.phi0().value() * settings_.kphi0pars()) + " " +
0192                       std::to_string(fpgapars_.d0().value() * settings_.kd0pars()) + " " +
0193                       std::to_string(fpgapars_.z0().value() * settings_.kz()) + " " +
0194                       std::to_string(fpgapars_.t().value() * settings_.ktpars());
0195     return oss;
0196   } else {
0197     std::string str = "";
0198     if (settings_.combined()) {
0199       if (seedIndex() == Seed::L1D1 || seedIndex() == Seed::L2D1) {
0200         str += outerFPGAStub_->phiregionstr() + "|";
0201       } else {
0202         str += innerFPGAStub_->phiregionstr() + "|";
0203       }
0204     }
0205     str += innerFPGAStub_->stubindex().str() + "|";
0206     if (middleFPGAStub_) {
0207       str += middleFPGAStub_->stubindex().str() + "|";
0208     }
0209     str += outerFPGAStub_->stubindex().str() + "|" + fpgapars_.rinv().str() + "|" + fpgapars_.phi0().str() + "|";
0210     if (middleFPGAStub_)
0211       str += fpgapars_.d0().str() + "|";
0212     str += fpgapars_.z0().str() + "|" + fpgapars_.t().str();
0213     return str;
0214   }
0215 }
0216 
0217 std::string Tracklet::vmstrlayer(int layer, unsigned int allstubindex) {
0218   FPGAWord index;
0219   if (allstubindex >= (1 << 7)) {
0220     edm::LogPrint("Tracklet") << "Warning projection number too large!";
0221     index.set((1 << 7) - 1, 7, true, __LINE__, __FILE__);
0222   } else {
0223     index.set(allstubindex, 7, true, __LINE__, __FILE__);
0224   }
0225 
0226   // This is a shortcut.
0227   //int irinvvm=16+(fpgarinv().value()>>(fpgarinv().nbits()-5));
0228   // rinv is not directly available in the TrackletProjection.
0229   // can be inferred from phi derivative: rinv = - phider * 2
0230   int tmp_irinv = proj_[layer - 1].fpgaphiprojder().value() * (-2);
0231   int nbits_irinv = proj_[layer - 1].fpgaphiprojder().nbits() + 1;
0232 
0233   // irinv in VMProjection:
0234   // top 5 bits of rinv and shifted to be positive
0235   int irinvvm = 16 + (tmp_irinv >> (nbits_irinv - 5));
0236 
0237   if (settings_.extended() && (irinvvm > 31)) {  //TODO - displaced tracking should protect against this
0238     edm::LogPrint("Tracklet") << "Warning irinvvm too large:" << irinvvm;
0239     irinvvm = 31;
0240   }
0241 
0242   assert(irinvvm >= 0);
0243   assert(irinvvm < 32);
0244   FPGAWord tmp;
0245   tmp.set(irinvvm, 5, true, __LINE__, __FILE__);
0246   std::string oss = index.str() + "|" + proj_[layer - 1].fpgarzbin1projvm().str() + "|" +
0247                     proj_[layer - 1].fpgarzbin2projvm().str() + "|" + proj_[layer - 1].fpgafinerzvm().str() + "|" +
0248                     proj_[layer - 1].fpgafinephivm().str() + "|" + tmp.str() + "|" + std::to_string(PSseed());
0249   return oss;
0250 }
0251 
0252 std::string Tracklet::vmstrdisk(int disk, unsigned int allstubindex) {
0253   FPGAWord index;
0254   if (allstubindex >= (1 << 7)) {
0255     edm::LogPrint("Tracklet") << "Warning projection number too large!";
0256     index.set((1 << 7) - 1, 7, true, __LINE__, __FILE__);
0257   } else {
0258     index.set(allstubindex, 7, true, __LINE__, __FILE__);
0259   }
0260   std::string oss =
0261       index.str() + "|" + proj_[N_LAYER + disk - 1].fpgarzbin1projvm().str() + "|" +
0262       proj_[N_LAYER + disk - 1].fpgarzbin2projvm().str() + "|" + proj_[N_LAYER + disk - 1].fpgafinerzvm().str() + "|" +
0263       proj_[N_LAYER + disk - 1].fpgafinephivm().str() + "|" + proj_[N_LAYER + disk - 1].getBendIndex().str();
0264   return oss;
0265 }
0266 
0267 std::string Tracklet::trackletprojstr(int layer) const {
0268   assert(layer > 0 && layer <= N_LAYER);
0269   FPGAWord tmp;
0270   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0271     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0272   }
0273   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0274   FPGAWord tcid;
0275   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0276 
0277   std::string oss = tcid.str() + "|" + tmp.str() + "|" + proj_[layer - 1].fpgaphiproj().str() + "|" +
0278                     proj_[layer - 1].fpgarzproj().str() + "|" + proj_[layer - 1].fpgaphiprojder().str() + "|" +
0279                     proj_[layer - 1].fpgarzprojder().str();
0280   return oss;
0281 }
0282 
0283 std::string Tracklet::trackletprojstrD(int disk) const {
0284   assert(abs(disk) <= N_DISK);
0285   FPGAWord tmp;
0286   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0287     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0288   }
0289   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0290   FPGAWord tcid;
0291   if (settings_.extended()) {
0292     tcid.set(TCIndex_, 8, true, __LINE__, __FILE__);
0293   } else {
0294     tcid.set(TCIndex_, 7, true, __LINE__, __FILE__);
0295   }
0296   std::string oss = tcid.str() + "|" + tmp.str() + "|" + proj_[N_LAYER + abs(disk) - 1].fpgaphiproj().str() + "|" +
0297                     proj_[N_LAYER + abs(disk) - 1].fpgarzproj().str() + "|" +
0298                     proj_[N_LAYER + abs(disk) - 1].fpgaphiprojder().str() + "|" +
0299                     proj_[N_LAYER + abs(disk) - 1].fpgarzprojder().str();
0300   return oss;
0301 }
0302 
0303 void Tracklet::addMatch(unsigned int layerdisk,
0304                         int ideltaphi,
0305                         int ideltarz,
0306                         double dphi,
0307                         double drz,
0308                         double dphiapprox,
0309                         double drzapprox,
0310                         int stubid,
0311                         const trklet::Stub* stubptr) {
0312   assert(layerdisk < N_LAYER + N_DISK);
0313   resid_[layerdisk].init(settings_, layerdisk, ideltaphi, ideltarz, stubid, dphi, drz, dphiapprox, drzapprox, stubptr);
0314 }
0315 
0316 std::string Tracklet::fullmatchstr(int layer) {
0317   assert(layer > 0 && layer <= N_LAYER);
0318 
0319   FPGAWord tmp;
0320   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0321     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0322   }
0323   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0324   FPGAWord tcid;
0325   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0326   std::string oss = tcid.str() + "|" + tmp.str() + "|" + resid_[layer - 1].fpgastubid().str() + "|" +
0327                     resid_[layer - 1].stubptr()->r().str() + "|" + resid_[layer - 1].fpgaphiresid().str() + "|" +
0328                     resid_[layer - 1].fpgarzresid().str();
0329   return oss;
0330 }
0331 
0332 std::string Tracklet::fullmatchdiskstr(int disk) {
0333   assert(disk > 0 && disk <= N_DISK);
0334 
0335   FPGAWord tmp;
0336   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0337     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0338   }
0339   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0340   FPGAWord tcid;
0341   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0342   const FPGAWord& stubr = resid_[N_LAYER + disk - 1].stubptr()->r();
0343   const bool isPS = resid_[N_LAYER + disk - 1].stubptr()->isPSmodule();
0344   std::string oss = tcid.str() + "|" + tmp.str() + "|" + resid_[N_LAYER + disk - 1].fpgastubid().str() + "|" +
0345                     (isPS ? stubr.str() : ("00000000" + stubr.str())) + "|" +
0346                     resid_[N_LAYER + disk - 1].fpgaphiresid().str() + "|" +
0347                     resid_[N_LAYER + disk - 1].fpgarzresid().str();
0348   return oss;
0349 }
0350 
0351 std::vector<const L1TStub*> Tracklet::getL1Stubs() {
0352   std::vector<const L1TStub*> tmp;
0353 
0354   if (innerFPGAStub_)
0355     tmp.push_back(innerFPGAStub_->l1tstub());
0356   if (middleFPGAStub_)
0357     tmp.push_back(middleFPGAStub_->l1tstub());
0358   if (outerFPGAStub_)
0359     tmp.push_back(outerFPGAStub_->l1tstub());
0360 
0361   for (const auto& iresid : resid_) {
0362     if (iresid.valid())
0363       tmp.push_back(iresid.stubptr()->l1tstub());
0364   }
0365 
0366   return tmp;
0367 }
0368 
0369 std::map<int, int> Tracklet::getStubIDs() {
0370   std::map<int, int> stubIDs;
0371 
0372   // For future reference, *resid_[i] uses i as the absolute stub index. (0-5 for barrel, 0-4 for disk)
0373   // On the other hand, proj*_[i] uses i almost like *resid_[i], except the *seeding* layer indices are removed entirely.
0374   // E.g. An L3L4 track has 0=L1, 1=L2, 2=L4, 3=L5 for the barrels (for proj*_[i])
0375 
0376   if (innerFPGAStub_)
0377     assert(innerFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0378   if (middleFPGAStub_)
0379     assert(middleFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0380   if (outerFPGAStub_)
0381     assert(outerFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0382 
0383   if (barrel_) {
0384     for (int i = 0; i < N_LAYER; i++) {
0385       //check barrel
0386       if (resid_[i].valid()) {
0387         // two extra bits to indicate if the matched stub is local or from neighbor
0388         int location = 1;  // local
0389         location <<= resid_[i].fpgastubid().nbits();
0390 
0391         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0392       }
0393 
0394       //check disk
0395       if (i >= N_DISK)
0396         continue;  //i=[0..4] for disks
0397       if (resid_[N_LAYER + i].valid()) {
0398         if (i == 3 && resid_[0].valid() && innerFPGAStub_->layer().value() == 1)
0399           continue;  // Don't add D4 if track has L1 stub
0400         // two extra bits to indicate if the matched stub is local or from neighbor
0401         int location = 1;  // local
0402         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0403 
0404         if (itfit().value() < 0) {
0405           stubIDs[-(N_LAYER + N_DISK) - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0406         } else {
0407           stubIDs[N_LAYER + N_DISK + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0408         }
0409       }
0410     }
0411 
0412     //get stubs making up tracklet
0413     if (innerFPGAStub_)
0414       stubIDs[innerFPGAStub_->layer().value() + 1] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0415     if (middleFPGAStub_)
0416       stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0417     if (outerFPGAStub_)
0418       stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0419 
0420   } else if (disk_) {
0421     for (int i = 0; i < N_DISK; i++) {
0422       //check barrel
0423       if (resid_[i].valid()) {
0424         // two extra bits to indicate if the matched stub is local or from neighbor
0425         int location = 1;  // local
0426         location <<= resid_[i].fpgastubid().nbits();
0427 
0428         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0429       }
0430 
0431       //check disks
0432       if (i == 4 && resid_[1].valid())
0433         continue;  // Don't add D5 if track has L2 stub
0434       if (resid_[N_LAYER + i].valid()) {
0435         // two extra bits to indicate if the matched stub is local or from neighbor
0436         int location = 1;  // local
0437         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0438 
0439         if (innerFPGAStub_->l1tstub()->disk() < 0) {
0440           stubIDs[-11 - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0441         } else {
0442           stubIDs[11 + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0443         }
0444       }
0445     }
0446 
0447     //get stubs making up tracklet
0448     if (innerFPGAStub_->disk().value() < 0) {  //negative side runs 6-10
0449       if (innerFPGAStub_)
0450         stubIDs[innerFPGAStub_->disk().value() - 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0451       if (middleFPGAStub_)
0452         stubIDs[middleFPGAStub_->disk().value() - 10] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0453       if (outerFPGAStub_)
0454         stubIDs[outerFPGAStub_->disk().value() - 10] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0455     } else {  // positive side runs 11-15]
0456       if (innerFPGAStub_)
0457         stubIDs[innerFPGAStub_->disk().value() + 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0458       if (middleFPGAStub_)
0459         stubIDs[middleFPGAStub_->disk().value() + 10] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0460       if (outerFPGAStub_)
0461         stubIDs[outerFPGAStub_->disk().value() + 10] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0462     }
0463 
0464   } else if (overlap_) {
0465     for (int i = 0; i < N_DISK; i++) {
0466       //check barrel
0467       if (resid_[i].valid()) {
0468         // two extra bits to indicate if the matched stub is local or from neighbor
0469         int location = 1;  // local
0470         location <<= resid_[i].fpgastubid().nbits();
0471 
0472         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0473       }
0474 
0475       //check disks
0476       if (resid_[N_LAYER + i].valid()) {
0477         // two extra bits to indicate if the matched stub is local or from neighbor
0478         int location = 1;  // local
0479         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0480 
0481         if (innerFPGAStub_->l1tstub()->disk() < 0) {  // if negative overlap
0482           if (innerFPGAStub_->layer().value() != 2 || !resid_[0].valid() ||
0483               i != 3) {  // Don't add D4 if this is an L3L2 track with an L1 stub
0484             stubIDs[-11 - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0485           }
0486         } else {
0487           if (innerFPGAStub_->layer().value() != 2 || !resid_[0].valid() || i != 3) {
0488             stubIDs[11 + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0489           }
0490         }
0491       }
0492     }
0493 
0494     //get stubs making up tracklet
0495 
0496     if (innerFPGAStub_->layer().value() == 2) {  // L3L2 track
0497       if (innerFPGAStub_)
0498         stubIDs[innerFPGAStub_->layer().value() + 1] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0499       if (middleFPGAStub_)
0500         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0501       if (outerFPGAStub_)
0502         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0503     } else if (innerFPGAStub_->disk().value() < 0) {  //negative side runs -11 - -15
0504       if (innerFPGAStub_)
0505         stubIDs[innerFPGAStub_->disk().value() - 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0506       if (middleFPGAStub_)
0507         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0508       if (outerFPGAStub_)
0509         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0510     } else {  // positive side runs 11-15]
0511       if (innerFPGAStub_)
0512         stubIDs[innerFPGAStub_->disk().value() + 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0513       if (middleFPGAStub_)
0514         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0515       if (outerFPGAStub_)
0516         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0517     }
0518   }
0519 
0520   return stubIDs;
0521 }
0522 
0523 void Tracklet::setFitPars(double rinvfit,
0524                           double phi0fit,
0525                           double d0fit,
0526                           double tfit,
0527                           double z0fit,
0528                           double chisqrphifit,
0529                           double chisqrzfit,
0530                           double rinvfitexact,
0531                           double phi0fitexact,
0532                           double d0fitexact,
0533                           double tfitexact,
0534                           double z0fitexact,
0535                           double chisqrphifitexact,
0536                           double chisqrzfitexact,
0537                           int irinvfit,
0538                           int iphi0fit,
0539                           int id0fit,
0540                           int itfit,
0541                           int iz0fit,
0542                           int ichisqrphifit,
0543                           int ichisqrzfit,
0544                           int hitpattern,
0545                           const vector<const L1TStub*>& l1stubs) {
0546   fitpars_.init(rinvfit, phi0fit, d0fit, tfit, z0fit);
0547   chisqrphifit_ = chisqrphifit;
0548   chisqrzfit_ = chisqrzfit;
0549 
0550   fitparsexact_.init(rinvfitexact, phi0fitexact, d0fitexact, tfitexact, z0fitexact);
0551   chisqrphifitexact_ = chisqrphifitexact;
0552   chisqrzfitexact_ = chisqrzfitexact;
0553 
0554   if (irinvfit > (1 << 14))
0555     irinvfit = (1 << 14);
0556   if (irinvfit <= -(1 << 14))
0557     irinvfit = -(1 << 14) + 1;
0558   fpgafitpars_.rinv().set(irinvfit, 15, false, __LINE__, __FILE__);
0559   fpgafitpars_.phi0().set(iphi0fit, 19, false, __LINE__, __FILE__);
0560   fpgafitpars_.d0().set(id0fit, 19, false, __LINE__, __FILE__);
0561   fpgafitpars_.t().set(itfit, 14, false, __LINE__, __FILE__);
0562 
0563   if (iz0fit >= (1 << (settings_.nbitsz0() - 1))) {
0564     iz0fit = (1 << (settings_.nbitsz0() - 1)) - 1;
0565   }
0566 
0567   if (iz0fit <= -(1 << (settings_.nbitsz0() - 1))) {
0568     iz0fit = 1 - (1 << (settings_.nbitsz0() - 1));
0569   }
0570 
0571   fpgafitpars_.z0().set(iz0fit, settings_.nbitsz0(), false, __LINE__, __FILE__);
0572   ichisqrphifit_.set(ichisqrphifit, 8, true, __LINE__, __FILE__);
0573   ichisqrzfit_.set(ichisqrzfit, 8, true, __LINE__, __FILE__);
0574 
0575   hitpattern_ = hitpattern;
0576 
0577   fpgatrack_ = std::make_unique<Track>(makeTrack(l1stubs));
0578 }
0579 
0580 const std::string Tracklet::layerstubstr(const unsigned layer) const {
0581   assert(layer < N_LAYER);
0582 
0583   std::stringstream oss("");
0584   if (!resid_[layer].valid())
0585     oss << "0|0000000|0000000000|0000000|000000000000|000000000";
0586   else {
0587     if (trackIndex_ < 0 || trackIndex_ > (int)settings_.ntrackletmax()) {
0588       cout << "trackIndex_ = " << trackIndex_ << endl;
0589       assert(0);
0590     }
0591     const FPGAWord tmp(trackIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0592     oss << "1|";  // valid bit
0593     oss << tmp.str() << "|";
0594     oss << resid_[layer].fpgastubid().str() << "|";
0595     oss << resid_[layer].stubptr()->r().str() << "|";
0596     oss << resid_[layer].fpgaphiresid().str() << "|";
0597     oss << resid_[layer].fpgarzresid().str();
0598   }
0599 
0600   return oss.str();
0601 }
0602 
0603 const std::string Tracklet::diskstubstr(const unsigned disk) const {
0604   assert(disk < N_DISK);
0605 
0606   std::stringstream oss("");
0607   if (!resid_[N_LAYER + disk].valid())
0608     oss << "0|0000000|0000000000|000000000000|000000000000|0000000";
0609   else {
0610     if (trackIndex_ < 0 || trackIndex_ > (int)settings_.ntrackletmax()) {
0611       cout << "trackIndex_ = " << trackIndex_ << endl;
0612       assert(0);
0613     }
0614     const FPGAWord tmp(trackIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0615     const FPGAWord& stubr = resid_[N_LAYER + disk].stubptr()->r();
0616     const bool isPS = resid_[N_LAYER + disk].stubptr()->isPSmodule();
0617     oss << "1|";  // valid bit
0618     oss << tmp.str() << "|";
0619     oss << resid_[N_LAYER + disk].fpgastubid().str() << "|";
0620     oss << (isPS ? stubr.str() : ("00000000" + stubr.str())) << "|";
0621     oss << resid_[N_LAYER + disk].fpgaphiresid().str() << "|";
0622     oss << resid_[N_LAYER + disk].fpgarzresid().str();
0623   }
0624 
0625   return oss.str();
0626 }
0627 
0628 std::string Tracklet::trackfitstr() const {
0629   const unsigned maxNHits = 8;
0630   const unsigned nBitsPerHit = 3;
0631   vector<string> stub(maxNHits, "0");
0632   string hitmap(maxNHits * nBitsPerHit, '0');
0633 
0634   // Assign stub strings for each of the possible projections for each seed.
0635   // The specific layers/disks for a given seed are determined by the wiring.
0636   switch (seedIndex()) {
0637     case 0:                       // L1L2
0638       stub[0] = layerstubstr(2);  // L3
0639       stub[1] = layerstubstr(3);  // L4
0640       stub[2] = layerstubstr(4);  // L5
0641       stub[3] = layerstubstr(5);  // L6
0642 
0643       stub[4] = diskstubstr(0);  // D1
0644       stub[5] = diskstubstr(1);  // D2
0645       stub[6] = diskstubstr(2);  // D3
0646       stub[7] = diskstubstr(3);  // D4
0647 
0648       break;
0649 
0650     case 1:                       // L2L3
0651       stub[0] = layerstubstr(0);  // L1
0652       stub[1] = layerstubstr(3);  // L4
0653       stub[2] = layerstubstr(4);  // L5
0654 
0655       stub[3] = diskstubstr(0);  // D1
0656       stub[4] = diskstubstr(1);  // D2
0657       stub[5] = diskstubstr(2);  // D3
0658       stub[6] = diskstubstr(3);  // D4
0659 
0660       break;
0661 
0662     case 2:                       // L3L4
0663       stub[0] = layerstubstr(0);  // L1
0664       stub[1] = layerstubstr(1);  // L2
0665       stub[2] = layerstubstr(4);  // L5
0666       stub[3] = layerstubstr(5);  // L6
0667 
0668       stub[4] = diskstubstr(0);  // D1
0669       stub[5] = diskstubstr(1);  // D2
0670 
0671       break;
0672 
0673     case 3:                       // L5L6
0674       stub[0] = layerstubstr(0);  // L1
0675       stub[1] = layerstubstr(1);  // L2
0676       stub[2] = layerstubstr(2);  // L3
0677       stub[3] = layerstubstr(3);  // L4
0678 
0679       break;
0680 
0681     case 4:                       // D1D2
0682       stub[0] = layerstubstr(0);  // L1
0683       stub[1] = layerstubstr(1);  // L2
0684 
0685       stub[2] = diskstubstr(2);  // D3
0686       stub[3] = diskstubstr(3);  // D4
0687       stub[4] = diskstubstr(4);  // D5
0688 
0689       break;
0690 
0691     case 5:                       // D3D4
0692       stub[0] = layerstubstr(0);  // L1
0693 
0694       stub[1] = diskstubstr(0);  // D1
0695       stub[2] = diskstubstr(1);  // D2
0696       stub[3] = diskstubstr(4);  // D5
0697 
0698       break;
0699 
0700     case 6:                      // L1D1
0701       stub[0] = diskstubstr(1);  // D2
0702       stub[1] = diskstubstr(2);  // D3
0703       stub[2] = diskstubstr(3);  // D4
0704       stub[3] = diskstubstr(4);  // D5
0705 
0706       break;
0707 
0708     case 7:                       // L2D1
0709       stub[0] = layerstubstr(0);  // L1
0710 
0711       stub[1] = diskstubstr(1);  // D2
0712       stub[2] = diskstubstr(2);  // D3
0713       stub[3] = diskstubstr(3);  // D4
0714 
0715       break;
0716   }
0717 
0718   // Only one hit per layer/disk is allowed currently, so the hit map for a
0719   // given layer/disk is just equal to the valid bit of the corresponding stub
0720   // string, which is the first character.
0721   for (unsigned i = 0; i < maxNHits; i++)
0722     hitmap[i * nBitsPerHit + 2] = stub[i][0];
0723 
0724   std::string oss("");
0725   //Binary print out
0726   if (!settings_.writeoutReal()) {
0727     const FPGAWord tmp(getISeed(), settings_.nbitsseed(), true, __LINE__, __FILE__);
0728 
0729     oss += "1|";  // valid bit
0730     oss += tmp.str() + "|";
0731     if (settings_.combined()) {
0732       if (seedIndex() == Seed::L1D1 || seedIndex() == Seed::L2D1) {
0733         oss += outerFPGAStub()->phiregionstr() + "|";
0734         oss += innerFPGAStub()->phiregionstr() + "|";
0735       } else {
0736         oss += innerFPGAStub()->phiregionstr() + "|";
0737         oss += outerFPGAStub()->phiregionstr() + "|";
0738       }
0739     }
0740     oss += innerFPGAStub()->stubindex().str() + "|";
0741     oss += outerFPGAStub()->stubindex().str() + "|";
0742     oss += fpgapars_.rinv().str() + "|";
0743     oss += fpgapars_.phi0().str() + "|";
0744     oss += fpgapars_.z0().str() + "|";
0745     oss += fpgapars_.t().str() + "|";
0746     oss += hitmap;
0747     for (unsigned i = 0; i < maxNHits; i++)
0748       // If a valid stub string was never assigned, then that stub is not
0749       // included in the output.
0750       if (stub[i] != "0")
0751         oss += "|" + stub[i];
0752   }
0753 
0754   return oss;
0755 }
0756 
0757 // Create a Track object from stubs & digitized track helix params
0758 
0759 Track Tracklet::makeTrack(const vector<const L1TStub*>& l1stubs) {
0760   assert(fit());
0761 
0762   // Digitized track helix params
0763   TrackPars<int> ipars(fpgafitpars_.rinv().value(),
0764                        fpgafitpars_.phi0().value(),
0765                        fpgafitpars_.d0().value(),
0766                        fpgafitpars_.t().value(),
0767                        fpgafitpars_.z0().value());
0768 
0769   // If fitter produced no stub list, take it from original tracklet.
0770   vector<const L1TStub*> tmp = l1stubs.empty() ? getL1Stubs() : l1stubs;
0771 
0772   vector<L1TStub> tmp2;
0773 
0774   tmp2.reserve(tmp.size());
0775   for (auto stub : tmp) {
0776     tmp2.push_back(*stub);
0777   }
0778 
0779   Track tmpTrack(ipars,
0780                  ichisqrphifit_.value(),
0781                  ichisqrzfit_.value(),
0782                  chisqrphifit_,
0783                  chisqrzfit_,
0784                  hitpattern_,
0785                  getStubIDs(),
0786                  tmp2,
0787                  getISeed());
0788 
0789   return tmpTrack;
0790 }
0791 
0792 int Tracklet::layer() const {
0793   int l1 = (innerFPGAStub_ && innerFPGAStub_->layerdisk() < N_LAYER) ? innerFPGAStub_->l1tstub()->layerdisk() + 1 : 999,
0794       l2 = (middleFPGAStub_ && middleFPGAStub_->layerdisk() < N_LAYER) ? middleFPGAStub_->l1tstub()->layerdisk() + 1
0795                                                                        : 999,
0796       l3 = (outerFPGAStub_ && outerFPGAStub_->layerdisk() < N_LAYER) ? outerFPGAStub_->l1tstub()->layerdisk() + 1 : 999,
0797       l = min(min(l1, l2), l3);
0798   return (l < 999 ? l : 0);
0799 }
0800 
0801 int Tracklet::disk() const {
0802   int d1 = (innerFPGAStub_ && (innerFPGAStub_->layerdisk() >= N_LAYER)) ? innerFPGAStub_->l1tstub()->disk() : 999,
0803       d2 = (middleFPGAStub_ && (middleFPGAStub_->layerdisk() >= N_LAYER)) ? middleFPGAStub_->l1tstub()->disk() : 999,
0804       d3 = (outerFPGAStub_ && (outerFPGAStub_->layerdisk() >= N_LAYER)) ? outerFPGAStub_->l1tstub()->disk() : 999,
0805       d = 999;
0806   if (abs(d1) < min(abs(d2), abs(d3)))
0807     d = d1;
0808   if (abs(d2) < min(abs(d1), abs(d3)))
0809     d = d2;
0810   if (abs(d3) < min(abs(d1), abs(d2)))
0811     d = d3;
0812   return (d < 999 ? d : 0);
0813 }
0814 
0815 void Tracklet::setTrackletIndex(unsigned int index) {
0816   trackletIndex_ = index;
0817   assert(index <= settings_.ntrackletmax());
0818 }
0819 
0820 int Tracklet::getISeed() const {
0821   const int iSeed = TCIndex_ >> settings_.nbitsitc();
0822   assert(iSeed >= 0 && iSeed <= (int)N_SEED);
0823   return iSeed;
0824 }
0825 
0826 int Tracklet::getITC() const {
0827   const int iSeed = getISeed(), iTC = TCIndex_ - (iSeed << settings_.nbitsitc());
0828   assert(iTC >= 0 && iTC <= 14);
0829   return iTC;
0830 }
0831 
0832 void Tracklet::setTrackIndex(int index) {
0833   trackIndex_ = index;
0834   assert(index <= (int)settings_.ntrackletmax());
0835 }
0836 
0837 int Tracklet::trackIndex() const { return trackIndex_; }