Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:50:30

0001 #ifndef L1_TRACK_TRIGGER_TRACK_WORD_H
0002 #define L1_TRACK_TRIGGER_TRACK_WORD_H
0003 
0004 ////////
0005 //
0006 // class to store the 96-bit track word produced by the L1 Track Trigger.  Intended to be inherited by L1 TTTrack.
0007 // packing scheme given below.
0008 //
0009 // author:      Mike Hildreth
0010 // modified by: Alexx Perloff
0011 // created:     April 9, 2019
0012 // modified:    March 9, 2021
0013 //
0014 ///////
0015 
0016 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
0017 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0018 #include "DataFormats/Math/interface/deltaPhi.h"
0019 
0020 #include <ap_int.h>
0021 
0022 #include <algorithm>
0023 #include <array>
0024 #include <bitset>
0025 #include <cmath>
0026 #include <limits>
0027 #include <string>
0028 #include <vector>
0029 
0030 namespace tttrack_trackword {
0031   void infoTestDigitizationScheme(
0032       const unsigned int, const double, const double, const unsigned int, const double, const unsigned int);
0033 }
0034 
0035 class TTTrack_TrackWord {
0036 public:
0037   // ----------constants, enums and typedefs ---------
0038   enum TrackBitWidths {
0039     // The sizes of the track word components
0040     kMVAOtherSize = 6,    // Space for two specialized MVA selections
0041     kMVAQualitySize = 3,  // Width of track quality MVA
0042     kHitPatternSize = 7,  // Width of the hit pattern for stubs
0043     kBendChi2Size = 3,    // Width of the bend-chi2/dof
0044     kD0Size = 13,         // Width of D0
0045     kChi2RZSize = 4,      // Width of chi2/dof for r-z
0046     kZ0Size = 12,         // Width of z-position (40cm / 0.1)
0047     kTanlSize = 16,       // Width of tan(lambda)
0048     kChi2RPhiSize = 4,    // Width of chi2/dof for r-phi
0049     kPhiSize = 12,        // Width of phi
0050     kRinvSize = 15,       // Width of Rinv
0051     kValidSize = 1,       // Valid bit
0052 
0053     kTrackWordSize = kValidSize + kRinvSize + kPhiSize + kChi2RPhiSize + kTanlSize + kZ0Size + kChi2RZSize + kD0Size +
0054                      kBendChi2Size + kHitPatternSize + kMVAQualitySize +
0055                      kMVAOtherSize,  // Width of the track word in bits
0056   };
0057 
0058   enum TrackBitLocations {
0059     // The location of the least significant bit (LSB) and most significant bit (MSB) in the track word for different fields
0060     kMVAOtherLSB = 0,
0061     kMVAOtherMSB = kMVAOtherLSB + TrackBitWidths::kMVAOtherSize - 1,
0062     kMVAQualityLSB = kMVAOtherMSB + 1,
0063     kMVAQualityMSB = kMVAQualityLSB + TrackBitWidths::kMVAQualitySize - 1,
0064     kHitPatternLSB = kMVAQualityMSB + 1,
0065     kHitPatternMSB = kHitPatternLSB + TrackBitWidths::kHitPatternSize - 1,
0066     kBendChi2LSB = kHitPatternMSB + 1,
0067     kBendChi2MSB = kBendChi2LSB + TrackBitWidths::kBendChi2Size - 1,
0068     kD0LSB = kBendChi2MSB + 1,
0069     kD0MSB = kD0LSB + TrackBitWidths::kD0Size - 1,
0070     kChi2RZLSB = kD0MSB + 1,
0071     kChi2RZMSB = kChi2RZLSB + TrackBitWidths::kChi2RZSize - 1,
0072     kZ0LSB = kChi2RZMSB + 1,
0073     kZ0MSB = kZ0LSB + TrackBitWidths::kZ0Size - 1,
0074     kTanlLSB = kZ0MSB + 1,
0075     kTanlMSB = kTanlLSB + TrackBitWidths::kTanlSize - 1,
0076     kChi2RPhiLSB = kTanlMSB + 1,
0077     kChi2RPhiMSB = kChi2RPhiLSB + TrackBitWidths::kChi2RPhiSize - 1,
0078     kPhiLSB = kChi2RPhiMSB + 1,
0079     kPhiMSB = kPhiLSB + TrackBitWidths::kPhiSize - 1,
0080     kRinvLSB = kPhiMSB + 1,
0081     kRinvMSB = kRinvLSB + TrackBitWidths::kRinvSize - 1,
0082     kValidLSB = kRinvMSB + 1,
0083     kValidMSB = kValidLSB + TrackBitWidths::kValidSize - 1,
0084   };
0085 
0086   // Binning constants
0087   static constexpr double minRinv = -0.006;
0088   static constexpr double minPhi0 = -0.7853981696;  // relative to the center of the sector
0089   static constexpr double minTanl = -8.;
0090   static constexpr double minZ0 = -20.46912512;
0091   static constexpr double minD0 = -16.;
0092 
0093   static constexpr double stepRinv = (2. * std::abs(minRinv)) / (1 << TrackBitWidths::kRinvSize);
0094   static constexpr double stepPhi0 = (2. * std::abs(minPhi0)) / (1 << TrackBitWidths::kPhiSize);
0095   static constexpr double stepTanL = (1. / (1 << 12));
0096   static constexpr double stepZ0 = (2. * std::abs(minZ0)) / (1 << TrackBitWidths::kZ0Size);
0097   static constexpr double stepD0 = (1. / (1 << 8));
0098 
0099   // Bin edges for chi2/dof
0100   static constexpr std::array<double, 1 << TrackBitWidths::kChi2RPhiSize> chi2RPhiBins = {
0101       {0.0, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0, 10.0, 15.0, 20.0, 35.0, 60.0, 200.0}};
0102   static constexpr std::array<double, 1 << TrackBitWidths::kChi2RZSize> chi2RZBins = {
0103       {0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 8.0, 10.0, 20.0, 50.0}};
0104   static constexpr std::array<double, 1 << TrackBitWidths::kBendChi2Size> bendChi2Bins = {
0105       {0.0, 0.75, 1.0, 1.5, 2.25, 3.5, 5.0, 20.0}};
0106 
0107   // Sector constants
0108   static constexpr unsigned int nSectors = 9;
0109   static constexpr double sectorWidth = (2. * M_PI) / nSectors;
0110 
0111   // Track flags
0112   typedef ap_uint<TrackBitWidths::kValidSize> valid_t;  // valid bit
0113 
0114   // Track parameters types
0115   typedef ap_uint<TrackBitWidths::kRinvSize> rinv_t;  // Track Rinv
0116   typedef ap_uint<TrackBitWidths::kPhiSize> phi_t;    // Track phi
0117   typedef ap_uint<TrackBitWidths::kTanlSize> tanl_t;  // Track tan(l)
0118   typedef ap_uint<TrackBitWidths::kZ0Size> z0_t;      // Track z
0119   typedef ap_uint<TrackBitWidths::kD0Size> d0_t;      // D0
0120 
0121   // Track quality types
0122   typedef ap_uint<TrackBitWidths::kChi2RPhiSize> chi2rphi_t;      // Chi2 r-phi
0123   typedef ap_uint<TrackBitWidths::kChi2RZSize> chi2rz_t;          // Chi2 r-z
0124   typedef ap_uint<TrackBitWidths::kBendChi2Size> bendChi2_t;      // Bend-Chi2
0125   typedef ap_uint<TrackBitWidths::kHitPatternSize> hit_t;         // Hit mask bits
0126   typedef ap_uint<TrackBitWidths::kMVAQualitySize> qualityMVA_t;  // Track quality MVA
0127   typedef ap_uint<TrackBitWidths::kMVAOtherSize> otherMVA_t;      // Specialized MVA selection
0128 
0129   // Track word types
0130   typedef std::bitset<TrackBitWidths::kTrackWordSize> tkword_bs_t;  // Entire track word;
0131   typedef ap_uint<TrackBitWidths::kTrackWordSize> tkword_t;         // Entire track word;
0132 
0133 public:
0134   // ----------Constructors --------------------------
0135   TTTrack_TrackWord() {}
0136   TTTrack_TrackWord(unsigned int valid,
0137                     const GlobalVector& momentum,
0138                     const GlobalPoint& POCA,
0139                     double rInv,
0140                     double chi2RPhi,  // would be xy chisq if chi2Z is non-zero
0141                     double chi2RZ,
0142                     double bendChi2,
0143                     unsigned int hitPattern,
0144                     unsigned int mvaQuality,
0145                     unsigned int mvaOther,
0146                     unsigned int sector);
0147   TTTrack_TrackWord(unsigned int valid,
0148                     unsigned int rInv,
0149                     unsigned int phi0,  // local phi
0150                     unsigned int tanl,
0151                     unsigned int z0,
0152                     unsigned int d0,
0153                     unsigned int chi2RPhi,  // would be total chisq if chi2Z is zero
0154                     unsigned int chi2RZ,
0155                     unsigned int bendChi2,
0156                     unsigned int hitPattern,
0157                     unsigned int mvaQuality,
0158                     unsigned int mvaOther);
0159 
0160   // ----------copy constructor ----------------------
0161   TTTrack_TrackWord(const TTTrack_TrackWord& word) { trackWord_ = word.trackWord_; }
0162 
0163   // ----------operators -----------------------------
0164   TTTrack_TrackWord& operator=(const TTTrack_TrackWord& word) {
0165     trackWord_ = word.trackWord_;
0166     return *this;
0167   }
0168 
0169   // ----------member functions (getters) ------------
0170   // These functions return arbitarary precision unsigned int words (lists of bits) for each quantity
0171   // Signed quantities have the sign enconded in the left-most bit.
0172   valid_t getValidWord() const { return getTrackWord()(TrackBitLocations::kValidMSB, TrackBitLocations::kValidLSB); }
0173   rinv_t getRinvWord() const { return getTrackWord()(TrackBitLocations::kRinvMSB, TrackBitLocations::kRinvLSB); }
0174   phi_t getPhiWord() const { return getTrackWord()(TrackBitLocations::kPhiMSB, TrackBitLocations::kPhiLSB); }
0175   tanl_t getTanlWord() const { return getTrackWord()(TrackBitLocations::kTanlMSB, TrackBitLocations::kTanlLSB); }
0176   z0_t getZ0Word() const { return getTrackWord()(TrackBitLocations::kZ0MSB, TrackBitLocations::kZ0LSB); }
0177   d0_t getD0Word() const { return getTrackWord()(TrackBitLocations::kD0MSB, TrackBitLocations::kD0LSB); }
0178   chi2rphi_t getChi2RPhiWord() const {
0179     return getTrackWord()(TrackBitLocations::kChi2RPhiMSB, TrackBitLocations::kChi2RPhiLSB);
0180   }
0181   chi2rz_t getChi2RZWord() const {
0182     return getTrackWord()(TrackBitLocations::kChi2RZMSB, TrackBitLocations::kChi2RZLSB);
0183   }
0184   bendChi2_t getBendChi2Word() const {
0185     return getTrackWord()(TrackBitLocations::kBendChi2MSB, TrackBitLocations::kBendChi2LSB);
0186   }
0187   hit_t getHitPatternWord() const {
0188     return getTrackWord()(TrackBitLocations::kHitPatternMSB, TrackBitLocations::kHitPatternLSB);
0189   }
0190   qualityMVA_t getMVAQualityWord() const {
0191     return getTrackWord()(TrackBitLocations::kMVAQualityMSB, TrackBitLocations::kMVAQualityLSB);
0192   }
0193   otherMVA_t getMVAOtherWord() const {
0194     return getTrackWord()(TrackBitLocations::kMVAOtherMSB, TrackBitLocations::kMVAOtherLSB);
0195   }
0196   tkword_t getTrackWord() const { return tkword_t(trackWord_.to_string().c_str(), 2); }
0197 
0198   // These functions return the packed bits in unsigned integer format for each quantity
0199   // Signed quantities have the sign enconded in the left-most bit of the pattern using
0200   //   a two's complement representation
0201   unsigned int getValidBits() const { return getValidWord().to_uint(); }
0202   unsigned int getRinvBits() const { return getRinvWord().to_uint(); }
0203   unsigned int getPhiBits() const { return getPhiWord().to_uint(); }
0204   unsigned int getTanlBits() const { return getTanlWord().to_uint(); }
0205   unsigned int getZ0Bits() const { return getZ0Word().to_uint(); }
0206   unsigned int getD0Bits() const { return getD0Word().to_uint(); }
0207   unsigned int getChi2RPhiBits() const { return getChi2RPhiWord().to_uint(); }
0208   unsigned int getChi2RZBits() const { return getChi2RZWord().to_uint(); }
0209   unsigned int getBendChi2Bits() const { return getBendChi2Word().to_uint(); }
0210   unsigned int getHitPatternBits() const { return getHitPatternWord().to_uint(); }
0211   unsigned int getMVAQualityBits() const { return getMVAQualityWord().to_uint(); }
0212   unsigned int getMVAOtherBits() const { return getMVAOtherWord().to_uint(); }
0213 
0214   // These functions return the unpacked and converted values
0215   // These functions return real numbers converted from the digitized quantities by unpacking the 96-bit track word
0216   bool getValid() const { return getValidWord().to_bool(); }
0217   double getRinv() const { return undigitizeSignedValue(getRinvBits(), TrackBitWidths::kRinvSize, stepRinv); }
0218   double getPhi() const { return undigitizeSignedValue(getPhiBits(), TrackBitWidths::kPhiSize, stepPhi0); }
0219   double getTanl() const { return undigitizeSignedValue(getTanlBits(), TrackBitWidths::kTanlSize, stepTanL); }
0220   double getZ0() const { return undigitizeSignedValue(getZ0Bits(), TrackBitWidths::kZ0Size, stepZ0); }
0221   double getD0() const { return undigitizeSignedValue(getD0Bits(), TrackBitWidths::kD0Size, stepD0); }
0222   double getChi2RPhi() const { return chi2RPhiBins[getChi2RPhiBits()]; }
0223   double getChi2RZ() const { return chi2RZBins[getChi2RZBits()]; }
0224   double getBendChi2() const { return bendChi2Bins[getBendChi2Bits()]; }
0225   unsigned int getHitPattern() const { return getHitPatternBits(); }
0226   unsigned int getNStubs() const { return countSetBits(getHitPatternBits()); }
0227   unsigned int getMVAQuality() const { return getMVAQualityBits(); }
0228   unsigned int getMVAOther() const { return getMVAOtherBits(); }
0229 
0230   // ----------member functions (setters) ------------
0231   void setTrackWord(unsigned int valid,
0232                     const GlobalVector& momentum,
0233                     const GlobalPoint& POCA,
0234                     double rInv,
0235                     double chi2RPhi,  // would be total chisq if chi2Z is zero
0236                     double chi2RZ,
0237                     double bendChi2,
0238                     unsigned int hitPattern,
0239                     unsigned int mvaQuality,
0240                     unsigned int mvaOther,
0241                     unsigned int sector);
0242 
0243   void setTrackWord(unsigned int valid,
0244                     unsigned int rInv,
0245                     unsigned int phi0,  // local phi
0246                     unsigned int tanl,
0247                     unsigned int z0,
0248                     unsigned int d0,
0249                     unsigned int chi2RPhi,  // would be total chisq if chi2Z is zero
0250                     unsigned int chi2RZ,
0251                     unsigned int bendChi2,
0252                     unsigned int hitPattern,
0253                     unsigned int mvaQuality,
0254                     unsigned int mvaOther);
0255 
0256   void setTrackWord(ap_uint<TrackBitWidths::kValidSize> valid,
0257                     ap_uint<TrackBitWidths::kRinvSize> rInv,
0258                     ap_uint<TrackBitWidths::kPhiSize> phi0,  // local phi
0259                     ap_uint<TrackBitWidths::kTanlSize> tanl,
0260                     ap_uint<TrackBitWidths::kZ0Size> z0,
0261                     ap_uint<TrackBitWidths::kD0Size> d0,
0262                     ap_uint<TrackBitWidths::kChi2RPhiSize> chi2RPhi,  // would be total chisq if chi2Z is zero
0263                     ap_uint<TrackBitWidths::kChi2RZSize> chi2RZ,
0264                     ap_uint<TrackBitWidths::kBendChi2Size> bendChi2,
0265                     ap_uint<TrackBitWidths::kHitPatternSize> hitPattern,
0266                     ap_uint<TrackBitWidths::kMVAQualitySize> mvaQuality,
0267                     ap_uint<TrackBitWidths::kMVAOtherSize> mvaOther);
0268 
0269   // ----------member functions (testers) ------------
0270   bool singleDigitizationSchemeTest(const double floatingPointValue, const unsigned int nBits, const double lsb) const;
0271   void testDigitizationScheme() const;
0272 
0273 protected:
0274   // ----------protected member functions ------------
0275   float localPhi(float globalPhi, unsigned int sector) const {
0276     return reco::deltaPhi(globalPhi, (sector * sectorWidth));
0277   }
0278 
0279 public:
0280   // ----------public member functions --------------
0281   unsigned int countSetBits(unsigned int n) const {
0282     // Adapted from: https://www.geeksforgeeks.org/count-set-bits-in-an-integer/
0283     unsigned int count = 0;
0284     while (n) {
0285       n &= (n - 1);
0286       count++;
0287     }
0288     return count;
0289   }
0290 
0291   unsigned int digitizeSignedValue(double value, unsigned int nBits, double lsb) const {
0292     // Digitize the incoming value
0293     int digitizedValue = std::floor(value / lsb);
0294 
0295     // Calculate the maxmum possible positive value given an output of nBits in size
0296     int digitizedMaximum = (1 << (nBits - 1)) - 1;  // The remove 1 bit from nBits to account for the sign
0297     int digitizedMinimum = -1. * (digitizedMaximum + 1);
0298 
0299     // Saturate the digitized value
0300     digitizedValue = std::clamp(digitizedValue, digitizedMinimum, digitizedMaximum);
0301 
0302     // Do the two's compliment encoding
0303     unsigned int twosValue = digitizedValue;
0304     if (digitizedValue < 0) {
0305       twosValue += (1 << nBits);
0306     }
0307 
0308     return twosValue;
0309   }
0310 
0311   template <typename T>
0312   constexpr unsigned int getBin(double value, const T& bins) const {
0313     auto up = std::upper_bound(bins.begin(), bins.end(), value);
0314     return (up - bins.begin() - 1);
0315   }
0316 
0317   double undigitizeSignedValue(unsigned int twosValue, unsigned int nBits, double lsb, double offset = 0.5) const {
0318     // Check that none of the bits above the nBits-1 bit, in a range of [0, nBits-1], are set.
0319     // This makes sure that it isn't possible for the value represented by `twosValue` to be
0320     //  any bigger than ((1 << nBits) - 1).
0321     assert((twosValue >> nBits) == 0);
0322 
0323     // Convert from twos compliment to C++ signed integer (normal digitized value)
0324     int digitizedValue = twosValue;
0325     if (twosValue & (1 << (nBits - 1))) {  // check if the twosValue is negative
0326       digitizedValue -= (1 << nBits);
0327     }
0328 
0329     // Convert to floating point value
0330     return (double(digitizedValue) + offset) * lsb;
0331   }
0332 
0333   // ----------member data ---------------------------
0334   tkword_bs_t trackWord_;
0335 };
0336 
0337 #endif