Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-07-07 22:33:35

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 = innerFPGAStub_->stubindex().str() + "|";
0198     if (middleFPGAStub_) {
0199       str += middleFPGAStub_->stubindex().str() + "|";
0200     }
0201     str += outerFPGAStub_->stubindex().str() + "|" + fpgapars_.rinv().str() + "|" + fpgapars_.phi0().str() + "|";
0202     if (middleFPGAStub_)
0203       str += fpgapars_.d0().str() + "|";
0204     str += fpgapars_.z0().str() + "|" + fpgapars_.t().str();
0205     return str;
0206   }
0207 }
0208 
0209 std::string Tracklet::vmstrlayer(int layer, unsigned int allstubindex) {
0210   FPGAWord index;
0211   if (allstubindex >= (1 << 7)) {
0212     edm::LogPrint("Tracklet") << "Warning projection number too large!";
0213     index.set((1 << 7) - 1, 7, true, __LINE__, __FILE__);
0214   } else {
0215     index.set(allstubindex, 7, true, __LINE__, __FILE__);
0216   }
0217 
0218   // This is a shortcut.
0219   //int irinvvm=16+(fpgarinv().value()>>(fpgarinv().nbits()-5));
0220   // rinv is not directly available in the TrackletProjection.
0221   // can be inferred from phi derivative: rinv = - phider * 2
0222   int tmp_irinv = proj_[layer - 1].fpgaphiprojder().value() * (-2);
0223   int nbits_irinv = proj_[layer - 1].fpgaphiprojder().nbits() + 1;
0224 
0225   // irinv in VMProjection:
0226   // top 5 bits of rinv and shifted to be positive
0227   int irinvvm = 16 + (tmp_irinv >> (nbits_irinv - 5));
0228 
0229   if (settings_.extended() && (irinvvm > 31)) {  //TODO - displaced tracking should protect against this
0230     edm::LogPrint("Tracklet") << "Warning irinvvm too large:" << irinvvm;
0231     irinvvm = 31;
0232   }
0233 
0234   assert(irinvvm >= 0);
0235   assert(irinvvm < 32);
0236   FPGAWord tmp;
0237   tmp.set(irinvvm, 5, true, __LINE__, __FILE__);
0238   std::string oss = index.str() + "|" + proj_[layer - 1].fpgarzbin1projvm().str() + "|" +
0239                     proj_[layer - 1].fpgarzbin2projvm().str() + "|" + proj_[layer - 1].fpgafinerzvm().str() + "|" +
0240                     proj_[layer - 1].fpgafinephivm().str() + "|" + tmp.str() + "|" + std::to_string(PSseed());
0241   return oss;
0242 }
0243 
0244 std::string Tracklet::vmstrdisk(int disk, unsigned int allstubindex) {
0245   FPGAWord index;
0246   if (allstubindex >= (1 << 7)) {
0247     edm::LogPrint("Tracklet") << "Warning projection number too large!";
0248     index.set((1 << 7) - 1, 7, true, __LINE__, __FILE__);
0249   } else {
0250     index.set(allstubindex, 7, true, __LINE__, __FILE__);
0251   }
0252   std::string oss =
0253       index.str() + "|" + proj_[N_LAYER + disk - 1].fpgarzbin1projvm().str() + "|" +
0254       proj_[N_LAYER + disk - 1].fpgarzbin2projvm().str() + "|" + proj_[N_LAYER + disk - 1].fpgafinerzvm().str() + "|" +
0255       proj_[N_LAYER + disk - 1].fpgafinephivm().str() + "|" + proj_[N_LAYER + disk - 1].getBendIndex().str();
0256   return oss;
0257 }
0258 
0259 std::string Tracklet::trackletprojstr(int layer) const {
0260   assert(layer > 0 && layer <= N_LAYER);
0261   FPGAWord tmp;
0262   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0263     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0264   }
0265   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0266   FPGAWord tcid;
0267   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0268 
0269   std::string oss = tcid.str() + "|" + tmp.str() + "|" + proj_[layer - 1].fpgaphiproj().str() + "|" +
0270                     proj_[layer - 1].fpgarzproj().str() + "|" + proj_[layer - 1].fpgaphiprojder().str() + "|" +
0271                     proj_[layer - 1].fpgarzprojder().str();
0272   return oss;
0273 }
0274 
0275 std::string Tracklet::trackletprojstrD(int disk) const {
0276   assert(abs(disk) <= N_DISK);
0277   FPGAWord tmp;
0278   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0279     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0280   }
0281   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0282   FPGAWord tcid;
0283   if (settings_.extended()) {
0284     tcid.set(TCIndex_, 8, true, __LINE__, __FILE__);
0285   } else {
0286     tcid.set(TCIndex_, 7, true, __LINE__, __FILE__);
0287   }
0288   std::string oss = tcid.str() + "|" + tmp.str() + "|" + proj_[N_LAYER + abs(disk) - 1].fpgaphiproj().str() + "|" +
0289                     proj_[N_LAYER + abs(disk) - 1].fpgarzproj().str() + "|" +
0290                     proj_[N_LAYER + abs(disk) - 1].fpgaphiprojder().str() + "|" +
0291                     proj_[N_LAYER + abs(disk) - 1].fpgarzprojder().str();
0292   return oss;
0293 }
0294 
0295 void Tracklet::addMatch(unsigned int layerdisk,
0296                         int ideltaphi,
0297                         int ideltarz,
0298                         double dphi,
0299                         double drz,
0300                         double dphiapprox,
0301                         double drzapprox,
0302                         int stubid,
0303                         const trklet::Stub* stubptr) {
0304   assert(layerdisk < N_LAYER + N_DISK);
0305   resid_[layerdisk].init(settings_, layerdisk, ideltaphi, ideltarz, stubid, dphi, drz, dphiapprox, drzapprox, stubptr);
0306 }
0307 
0308 std::string Tracklet::fullmatchstr(int layer) {
0309   assert(layer > 0 && layer <= N_LAYER);
0310 
0311   FPGAWord tmp;
0312   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0313     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0314   }
0315   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0316   FPGAWord tcid;
0317   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0318   std::string oss = tcid.str() + "|" + tmp.str() + "|" + resid_[layer - 1].fpgastubid().str() + "|" +
0319                     resid_[layer - 1].stubptr()->r().str() + "|" + resid_[layer - 1].fpgaphiresid().str() + "|" +
0320                     resid_[layer - 1].fpgarzresid().str();
0321   return oss;
0322 }
0323 
0324 std::string Tracklet::fullmatchdiskstr(int disk) {
0325   assert(disk > 0 && disk <= N_DISK);
0326 
0327   FPGAWord tmp;
0328   if (trackletIndex_ < 0 || trackletIndex_ > (int)settings_.ntrackletmax()) {
0329     throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " trackletIndex_ = " << trackletIndex_;
0330   }
0331   tmp.set(trackletIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0332   FPGAWord tcid;
0333   tcid.set(TCIndex_, settings_.nbitstcindex(), true, __LINE__, __FILE__);
0334   const FPGAWord& stubr = resid_[N_LAYER + disk - 1].stubptr()->r();
0335   const bool isPS = resid_[N_LAYER + disk - 1].stubptr()->isPSmodule();
0336   std::string oss = tcid.str() + "|" + tmp.str() + "|" + resid_[N_LAYER + disk - 1].fpgastubid().str() + "|" +
0337                     (isPS ? stubr.str() : ("00000000" + stubr.str())) + "|" +
0338                     resid_[N_LAYER + disk - 1].fpgaphiresid().str() + "|" +
0339                     resid_[N_LAYER + disk - 1].fpgarzresid().str();
0340   return oss;
0341 }
0342 
0343 std::vector<const L1TStub*> Tracklet::getL1Stubs() {
0344   std::vector<const L1TStub*> tmp;
0345 
0346   if (innerFPGAStub_)
0347     tmp.push_back(innerFPGAStub_->l1tstub());
0348   if (middleFPGAStub_)
0349     tmp.push_back(middleFPGAStub_->l1tstub());
0350   if (outerFPGAStub_)
0351     tmp.push_back(outerFPGAStub_->l1tstub());
0352 
0353   for (const auto& iresid : resid_) {
0354     if (iresid.valid())
0355       tmp.push_back(iresid.stubptr()->l1tstub());
0356   }
0357 
0358   return tmp;
0359 }
0360 
0361 std::map<int, int> Tracklet::getStubIDs() {
0362   std::map<int, int> stubIDs;
0363 
0364   // For future reference, *resid_[i] uses i as the absolute stub index. (0-5 for barrel, 0-4 for disk)
0365   // On the other hand, proj*_[i] uses i almost like *resid_[i], except the *seeding* layer indices are removed entirely.
0366   // E.g. An L3L4 track has 0=L1, 1=L2, 2=L4, 3=L5 for the barrels (for proj*_[i])
0367 
0368   if (innerFPGAStub_)
0369     assert(innerFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0370   if (middleFPGAStub_)
0371     assert(middleFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0372   if (outerFPGAStub_)
0373     assert(outerFPGAStub_->stubindex().nbits() == N_BITSMEMADDRESS);
0374 
0375   if (barrel_) {
0376     for (int i = 0; i < N_LAYER; i++) {
0377       //check barrel
0378       if (resid_[i].valid()) {
0379         // two extra bits to indicate if the matched stub is local or from neighbor
0380         int location = 1;  // local
0381         location <<= resid_[i].fpgastubid().nbits();
0382 
0383         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0384       }
0385 
0386       //check disk
0387       if (i >= N_DISK)
0388         continue;  //i=[0..4] for disks
0389       if (resid_[N_LAYER + i].valid()) {
0390         if (i == 3 && resid_[0].valid() && innerFPGAStub_->layer().value() == 1)
0391           continue;  // Don't add D4 if track has L1 stub
0392         // two extra bits to indicate if the matched stub is local or from neighbor
0393         int location = 1;  // local
0394         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0395 
0396         if (itfit().value() < 0) {
0397           stubIDs[-(N_LAYER + N_DISK) - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0398         } else {
0399           stubIDs[N_LAYER + N_DISK + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0400         }
0401       }
0402     }
0403 
0404     //get stubs making up tracklet
0405     if (innerFPGAStub_)
0406       stubIDs[innerFPGAStub_->layer().value() + 1] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0407     if (middleFPGAStub_)
0408       stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0409     if (outerFPGAStub_)
0410       stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0411 
0412   } else if (disk_) {
0413     for (int i = 0; i < N_DISK; i++) {
0414       //check barrel
0415       if (resid_[i].valid()) {
0416         // two extra bits to indicate if the matched stub is local or from neighbor
0417         int location = 1;  // local
0418         location <<= resid_[i].fpgastubid().nbits();
0419 
0420         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0421       }
0422 
0423       //check disks
0424       if (i == 4 && resid_[1].valid())
0425         continue;  // Don't add D5 if track has L2 stub
0426       if (resid_[N_LAYER + i].valid()) {
0427         // two extra bits to indicate if the matched stub is local or from neighbor
0428         int location = 1;  // local
0429         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0430 
0431         if (innerFPGAStub_->l1tstub()->disk() < 0) {
0432           stubIDs[-11 - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0433         } else {
0434           stubIDs[11 + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0435         }
0436       }
0437     }
0438 
0439     //get stubs making up tracklet
0440     if (innerFPGAStub_->disk().value() < 0) {  //negative side runs 6-10
0441       if (innerFPGAStub_)
0442         stubIDs[innerFPGAStub_->disk().value() - 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0443       if (middleFPGAStub_)
0444         stubIDs[middleFPGAStub_->disk().value() - 10] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0445       if (outerFPGAStub_)
0446         stubIDs[outerFPGAStub_->disk().value() - 10] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0447     } else {  // positive side runs 11-15]
0448       if (innerFPGAStub_)
0449         stubIDs[innerFPGAStub_->disk().value() + 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0450       if (middleFPGAStub_)
0451         stubIDs[middleFPGAStub_->disk().value() + 10] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0452       if (outerFPGAStub_)
0453         stubIDs[outerFPGAStub_->disk().value() + 10] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0454     }
0455 
0456   } else if (overlap_) {
0457     for (int i = 0; i < N_DISK; i++) {
0458       //check barrel
0459       if (resid_[i].valid()) {
0460         // two extra bits to indicate if the matched stub is local or from neighbor
0461         int location = 1;  // local
0462         location <<= resid_[i].fpgastubid().nbits();
0463 
0464         stubIDs[1 + i] = resid_[i].fpgastubid().value() + location;
0465       }
0466 
0467       //check disks
0468       if (resid_[N_LAYER + i].valid()) {
0469         // two extra bits to indicate if the matched stub is local or from neighbor
0470         int location = 1;  // local
0471         location <<= resid_[N_LAYER + i].fpgastubid().nbits();
0472 
0473         if (innerFPGAStub_->l1tstub()->disk() < 0) {  // if negative overlap
0474           if (innerFPGAStub_->layer().value() != 2 || !resid_[0].valid() ||
0475               i != 3) {  // Don't add D4 if this is an L3L2 track with an L1 stub
0476             stubIDs[-11 - i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0477           }
0478         } else {
0479           if (innerFPGAStub_->layer().value() != 2 || !resid_[0].valid() || i != 3) {
0480             stubIDs[11 + i] = resid_[N_LAYER + i].fpgastubid().value() + location;
0481           }
0482         }
0483       }
0484     }
0485 
0486     //get stubs making up tracklet
0487 
0488     if (innerFPGAStub_->layer().value() == 2) {  // L3L2 track
0489       if (innerFPGAStub_)
0490         stubIDs[innerFPGAStub_->layer().value() + 1] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0491       if (middleFPGAStub_)
0492         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0493       if (outerFPGAStub_)
0494         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0495     } else if (innerFPGAStub_->disk().value() < 0) {  //negative side runs -11 - -15
0496       if (innerFPGAStub_)
0497         stubIDs[innerFPGAStub_->disk().value() - 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0498       if (middleFPGAStub_)
0499         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0500       if (outerFPGAStub_)
0501         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0502     } else {  // positive side runs 11-15]
0503       if (innerFPGAStub_)
0504         stubIDs[innerFPGAStub_->disk().value() + 10] = innerFPGAStub_->phiregionaddress() + (1 << 10);
0505       if (middleFPGAStub_)
0506         stubIDs[middleFPGAStub_->layer().value() + 1] = middleFPGAStub_->phiregionaddress() + (1 << 10);
0507       if (outerFPGAStub_)
0508         stubIDs[outerFPGAStub_->layer().value() + 1] = outerFPGAStub_->phiregionaddress() + (1 << 10);
0509     }
0510   }
0511 
0512   return stubIDs;
0513 }
0514 
0515 void Tracklet::setFitPars(double rinvfit,
0516                           double phi0fit,
0517                           double d0fit,
0518                           double tfit,
0519                           double z0fit,
0520                           double chisqrphifit,
0521                           double chisqrzfit,
0522                           double rinvfitexact,
0523                           double phi0fitexact,
0524                           double d0fitexact,
0525                           double tfitexact,
0526                           double z0fitexact,
0527                           double chisqrphifitexact,
0528                           double chisqrzfitexact,
0529                           int irinvfit,
0530                           int iphi0fit,
0531                           int id0fit,
0532                           int itfit,
0533                           int iz0fit,
0534                           int ichisqrphifit,
0535                           int ichisqrzfit,
0536                           int hitpattern,
0537                           const vector<const L1TStub*>& l1stubs) {
0538   fitpars_.init(rinvfit, phi0fit, d0fit, tfit, z0fit);
0539   chisqrphifit_ = chisqrphifit;
0540   chisqrzfit_ = chisqrzfit;
0541 
0542   fitparsexact_.init(rinvfitexact, phi0fitexact, d0fitexact, tfitexact, z0fitexact);
0543   chisqrphifitexact_ = chisqrphifitexact;
0544   chisqrzfitexact_ = chisqrzfitexact;
0545 
0546   if (irinvfit > (1 << 14))
0547     irinvfit = (1 << 14);
0548   if (irinvfit <= -(1 << 14))
0549     irinvfit = -(1 << 14) + 1;
0550   fpgafitpars_.rinv().set(irinvfit, 15, false, __LINE__, __FILE__);
0551   fpgafitpars_.phi0().set(iphi0fit, 19, false, __LINE__, __FILE__);
0552   fpgafitpars_.d0().set(id0fit, 19, false, __LINE__, __FILE__);
0553   fpgafitpars_.t().set(itfit, 14, false, __LINE__, __FILE__);
0554 
0555   if (iz0fit >= (1 << (settings_.nbitsz0() - 1))) {
0556     iz0fit = (1 << (settings_.nbitsz0() - 1)) - 1;
0557   }
0558 
0559   if (iz0fit <= -(1 << (settings_.nbitsz0() - 1))) {
0560     iz0fit = 1 - (1 << (settings_.nbitsz0() - 1));
0561   }
0562 
0563   fpgafitpars_.z0().set(iz0fit, settings_.nbitsz0(), false, __LINE__, __FILE__);
0564   ichisqrphifit_.set(ichisqrphifit, 8, true, __LINE__, __FILE__);
0565   ichisqrzfit_.set(ichisqrzfit, 8, true, __LINE__, __FILE__);
0566 
0567   hitpattern_ = hitpattern;
0568 
0569   fpgatrack_ = std::make_unique<Track>(makeTrack(l1stubs));
0570 }
0571 
0572 const std::string Tracklet::layerstubstr(const unsigned layer) const {
0573   assert(layer < N_LAYER);
0574 
0575   std::stringstream oss("");
0576   if (!resid_[layer].valid())
0577     oss << "0|0000000|0000000000|0000000|000000000000|000000000";
0578   else {
0579     if (trackIndex_ < 0 || trackIndex_ > (int)settings_.ntrackletmax()) {
0580       cout << "trackIndex_ = " << trackIndex_ << endl;
0581       assert(0);
0582     }
0583     const FPGAWord tmp(trackIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0584     oss << "1|";  // valid bit
0585     oss << tmp.str() << "|";
0586     oss << resid_[layer].fpgastubid().str() << "|";
0587     oss << resid_[layer].stubptr()->r().str() << "|";
0588     oss << resid_[layer].fpgaphiresid().str() << "|";
0589     oss << resid_[layer].fpgarzresid().str();
0590   }
0591 
0592   return oss.str();
0593 }
0594 
0595 const std::string Tracklet::diskstubstr(const unsigned disk) const {
0596   assert(disk < N_DISK);
0597 
0598   std::stringstream oss("");
0599   if (!resid_[N_LAYER + disk].valid())
0600     oss << "0|0000000|0000000000|000000000000|000000000000|0000000";
0601   else {
0602     if (trackIndex_ < 0 || trackIndex_ > (int)settings_.ntrackletmax()) {
0603       cout << "trackIndex_ = " << trackIndex_ << endl;
0604       assert(0);
0605     }
0606     const FPGAWord tmp(trackIndex_, settings_.nbitstrackletindex(), true, __LINE__, __FILE__);
0607     const FPGAWord& stubr = resid_[N_LAYER + disk].stubptr()->r();
0608     const bool isPS = resid_[N_LAYER + disk].stubptr()->isPSmodule();
0609     oss << "1|";  // valid bit
0610     oss << tmp.str() << "|";
0611     oss << resid_[N_LAYER + disk].fpgastubid().str() << "|";
0612     oss << (isPS ? stubr.str() : ("00000000" + stubr.str())) << "|";
0613     oss << resid_[N_LAYER + disk].fpgaphiresid().str() << "|";
0614     oss << resid_[N_LAYER + disk].fpgarzresid().str();
0615   }
0616 
0617   return oss.str();
0618 }
0619 
0620 std::string Tracklet::trackfitstr() const {
0621   const unsigned maxNHits = 8;
0622   const unsigned nBitsPerHit = 3;
0623   vector<string> stub(maxNHits, "0");
0624   string hitmap(maxNHits * nBitsPerHit, '0');
0625 
0626   // Assign stub strings for each of the possible projections for each seed.
0627   // The specific layers/disks for a given seed are determined by the wiring.
0628   switch (seedIndex()) {
0629     case 0:                       // L1L2
0630       stub[0] = layerstubstr(2);  // L3
0631       stub[1] = layerstubstr(3);  // L4
0632       stub[2] = layerstubstr(4);  // L5
0633       stub[3] = layerstubstr(5);  // L6
0634 
0635       stub[4] = diskstubstr(0);  // D1
0636       stub[5] = diskstubstr(1);  // D2
0637       stub[6] = diskstubstr(2);  // D3
0638       stub[7] = diskstubstr(3);  // D4
0639 
0640       break;
0641 
0642     case 1:                       // L2L3
0643       stub[0] = layerstubstr(0);  // L1
0644       stub[1] = layerstubstr(3);  // L4
0645       stub[2] = layerstubstr(4);  // L5
0646 
0647       stub[3] = diskstubstr(0);  // D1
0648       stub[4] = diskstubstr(1);  // D2
0649       stub[5] = diskstubstr(2);  // D3
0650       stub[6] = diskstubstr(3);  // D4
0651 
0652       break;
0653 
0654     case 2:                       // L3L4
0655       stub[0] = layerstubstr(0);  // L1
0656       stub[1] = layerstubstr(1);  // L2
0657       stub[2] = layerstubstr(4);  // L5
0658       stub[3] = layerstubstr(5);  // L6
0659 
0660       stub[4] = diskstubstr(0);  // D1
0661       stub[5] = diskstubstr(1);  // D2
0662 
0663       break;
0664 
0665     case 3:                       // L5L6
0666       stub[0] = layerstubstr(0);  // L1
0667       stub[1] = layerstubstr(1);  // L2
0668       stub[2] = layerstubstr(2);  // L3
0669       stub[3] = layerstubstr(3);  // L4
0670 
0671       break;
0672 
0673     case 4:                       // D1D2
0674       stub[0] = layerstubstr(0);  // L1
0675       stub[1] = layerstubstr(1);  // L2
0676 
0677       stub[2] = diskstubstr(2);  // D3
0678       stub[3] = diskstubstr(3);  // D4
0679       stub[4] = diskstubstr(4);  // D5
0680 
0681       break;
0682 
0683     case 5:                       // D3D4
0684       stub[0] = layerstubstr(0);  // L1
0685 
0686       stub[1] = diskstubstr(0);  // D1
0687       stub[2] = diskstubstr(1);  // D2
0688       stub[3] = diskstubstr(4);  // D5
0689 
0690       break;
0691 
0692     case 6:                      // L1D1
0693       stub[0] = diskstubstr(1);  // D2
0694       stub[1] = diskstubstr(2);  // D3
0695       stub[2] = diskstubstr(3);  // D4
0696       stub[3] = diskstubstr(4);  // D5
0697 
0698       break;
0699 
0700     case 7:                       // L2D1
0701       stub[0] = layerstubstr(0);  // L1
0702 
0703       stub[1] = diskstubstr(1);  // D2
0704       stub[2] = diskstubstr(2);  // D3
0705       stub[3] = diskstubstr(3);  // D4
0706 
0707       break;
0708   }
0709 
0710   // Only one hit per layer/disk is allowed currently, so the hit map for a
0711   // given layer/disk is just equal to the valid bit of the corresponding stub
0712   // string, which is the first character.
0713   for (unsigned i = 0; i < maxNHits; i++)
0714     hitmap[i * nBitsPerHit + 2] = stub[i][0];
0715 
0716   std::string oss("");
0717   //Binary print out
0718   if (!settings_.writeoutReal()) {
0719     const FPGAWord tmp(getISeed(), settings_.nbitsseed(), true, __LINE__, __FILE__);
0720 
0721     oss += "1|";  // valid bit
0722     oss += tmp.str() + "|";
0723     oss += fpgapars_.rinv().str() + "|";
0724     oss += fpgapars_.phi0().str() + "|";
0725     oss += fpgapars_.z0().str() + "|";
0726     oss += fpgapars_.t().str() + "|";
0727     oss += hitmap;
0728     for (unsigned i = 0; i < maxNHits; i++)
0729       // If a valid stub string was never assigned, then that stub is not
0730       // included in the output.
0731       if (stub[i] != "0")
0732         oss += "|" + stub[i];
0733   }
0734 
0735   return oss;
0736 }
0737 
0738 Track Tracklet::makeTrack(const vector<const L1TStub*>& l1stubs) {
0739   assert(fit());
0740 
0741   TrackPars<int> ipars(fpgafitpars_.rinv().value(),
0742                        fpgafitpars_.phi0().value(),
0743                        fpgafitpars_.d0().value(),
0744                        fpgafitpars_.t().value(),
0745                        fpgafitpars_.z0().value());
0746 
0747   // If fitter produced no stub list, take it from original tracklet.
0748   vector<const L1TStub*> tmp = l1stubs.empty() ? getL1Stubs() : l1stubs;
0749 
0750   vector<L1TStub> tmp2;
0751 
0752   tmp2.reserve(tmp.size());
0753   for (auto stub : tmp) {
0754     tmp2.push_back(*stub);
0755   }
0756 
0757   Track tmpTrack(ipars,
0758                  ichisqrphifit_.value(),
0759                  ichisqrzfit_.value(),
0760                  chisqrphifit_,
0761                  chisqrzfit_,
0762                  hitpattern_,
0763                  getStubIDs(),
0764                  tmp2,
0765                  getISeed());
0766 
0767   return tmpTrack;
0768 }
0769 
0770 int Tracklet::layer() const {
0771   int l1 = (innerFPGAStub_ && innerFPGAStub_->layerdisk() < N_LAYER) ? innerFPGAStub_->l1tstub()->layerdisk() + 1 : 999,
0772       l2 = (middleFPGAStub_ && middleFPGAStub_->layerdisk() < N_LAYER) ? middleFPGAStub_->l1tstub()->layerdisk() + 1
0773                                                                        : 999,
0774       l3 = (outerFPGAStub_ && outerFPGAStub_->layerdisk() < N_LAYER) ? outerFPGAStub_->l1tstub()->layerdisk() + 1 : 999,
0775       l = min(min(l1, l2), l3);
0776   return (l < 999 ? l : 0);
0777 }
0778 
0779 int Tracklet::disk() const {
0780   int d1 = (innerFPGAStub_ && (innerFPGAStub_->layerdisk() >= N_LAYER)) ? innerFPGAStub_->l1tstub()->disk() : 999,
0781       d2 = (middleFPGAStub_ && (middleFPGAStub_->layerdisk() >= N_LAYER)) ? middleFPGAStub_->l1tstub()->disk() : 999,
0782       d3 = (outerFPGAStub_ && (outerFPGAStub_->layerdisk() >= N_LAYER)) ? outerFPGAStub_->l1tstub()->disk() : 999,
0783       d = 999;
0784   if (abs(d1) < min(abs(d2), abs(d3)))
0785     d = d1;
0786   if (abs(d2) < min(abs(d1), abs(d3)))
0787     d = d2;
0788   if (abs(d3) < min(abs(d1), abs(d2)))
0789     d = d3;
0790   return (d < 999 ? d : 0);
0791 }
0792 
0793 void Tracklet::setTrackletIndex(unsigned int index) {
0794   trackletIndex_ = index;
0795   assert(index <= settings_.ntrackletmax());
0796 }
0797 
0798 int Tracklet::getISeed() const {
0799   const int iSeed = TCIndex_ >> settings_.nbitsitc();
0800   assert(iSeed >= 0 && iSeed <= (int)N_SEED);
0801   return iSeed;
0802 }
0803 
0804 int Tracklet::getITC() const {
0805   const int iSeed = getISeed(), iTC = TCIndex_ - (iSeed << settings_.nbitsitc());
0806   assert(iTC >= 0 && iTC <= 14);
0807   return iTC;
0808 }
0809 
0810 void Tracklet::setTrackIndex(int index) {
0811   trackIndex_ = index;
0812   assert(index <= (int)settings_.ntrackletmax());
0813 }
0814 
0815 int Tracklet::trackIndex() const { return trackIndex_; }