Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-06-04 04:34:44

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   static constexpr int kTrackWordSize = kValidSize + kRinvSize + kPhiSize + kChi2RPhiSize + kTanlSize + kZ0Size +
0054                                         kChi2RZSize + kD0Size + 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   // Bin edges for TQ MVA
0108   static constexpr std::array<double, 1 << TrackBitWidths::kMVAQualitySize> tqMVABins = {
0109       {0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.750, 0.875}};
0110 
0111   // Sector constants
0112   static constexpr unsigned int nSectors = 9;
0113   static constexpr double sectorWidth = (2. * M_PI) / nSectors;
0114 
0115   // Track flags
0116   typedef ap_uint<TrackBitWidths::kValidSize> valid_t;  // valid bit
0117 
0118   // Track parameters types
0119   typedef ap_uint<TrackBitWidths::kRinvSize> rinv_t;  // Track Rinv
0120   typedef ap_uint<TrackBitWidths::kPhiSize> phi_t;    // Track phi
0121   typedef ap_uint<TrackBitWidths::kTanlSize> tanl_t;  // Track tan(l)
0122   typedef ap_uint<TrackBitWidths::kZ0Size> z0_t;      // Track z
0123   typedef ap_uint<TrackBitWidths::kD0Size> d0_t;      // D0
0124 
0125   // Track quality types
0126   typedef ap_uint<TrackBitWidths::kChi2RPhiSize> chi2rphi_t;      // Chi2 r-phi
0127   typedef ap_uint<TrackBitWidths::kChi2RZSize> chi2rz_t;          // Chi2 r-z
0128   typedef ap_uint<TrackBitWidths::kBendChi2Size> bendChi2_t;      // Bend-Chi2
0129   typedef ap_uint<TrackBitWidths::kHitPatternSize> hit_t;         // Hit mask bits
0130   typedef ap_uint<TrackBitWidths::kMVAQualitySize> qualityMVA_t;  // Track quality MVA
0131   typedef ap_uint<TrackBitWidths::kMVAOtherSize> otherMVA_t;      // Specialized MVA selection
0132 
0133   // Track word types
0134   typedef std::bitset<kTrackWordSize> tkword_bs_t;  // Entire track word;
0135   typedef ap_uint<kTrackWordSize> tkword_t;         // Entire track word;
0136 
0137 public:
0138   // ----------Constructors --------------------------
0139   TTTrack_TrackWord() {}
0140   TTTrack_TrackWord(unsigned int valid,
0141                     const GlobalVector& momentum,
0142                     const GlobalPoint& POCA,
0143                     double rInv,
0144                     double chi2RPhi,  // would be xy chisq if chi2Z is non-zero
0145                     double chi2RZ,
0146                     double bendChi2,
0147                     unsigned int hitPattern,
0148                     double mvaQuality,
0149                     double mvaOther,
0150                     unsigned int sector);
0151   TTTrack_TrackWord(unsigned int valid,
0152                     unsigned int rInv,
0153                     unsigned int phi0,  // local phi
0154                     unsigned int tanl,
0155                     unsigned int z0,
0156                     unsigned int d0,
0157                     unsigned int chi2RPhi,  // would be total chisq if chi2Z is zero
0158                     unsigned int chi2RZ,
0159                     unsigned int bendChi2,
0160                     unsigned int hitPattern,
0161                     unsigned int mvaQuality,
0162                     unsigned int mvaOther);
0163 
0164   // ----------copy constructor ----------------------
0165   TTTrack_TrackWord(const TTTrack_TrackWord& word) { trackWord_ = word.trackWord_; }
0166 
0167   // ----------operators -----------------------------
0168   TTTrack_TrackWord& operator=(const TTTrack_TrackWord& word) {
0169     trackWord_ = word.trackWord_;
0170     return *this;
0171   }
0172 
0173   // ----------member functions (getters) ------------
0174   // These functions return arbitarary precision unsigned int words (lists of bits) for each quantity
0175   // Signed quantities have the sign enconded in the left-most bit.
0176   valid_t getValidWord() const { return getTrackWord()(TrackBitLocations::kValidMSB, TrackBitLocations::kValidLSB); }
0177   rinv_t getRinvWord() const { return getTrackWord()(TrackBitLocations::kRinvMSB, TrackBitLocations::kRinvLSB); }
0178   phi_t getPhiWord() const { return getTrackWord()(TrackBitLocations::kPhiMSB, TrackBitLocations::kPhiLSB); }
0179   tanl_t getTanlWord() const { return getTrackWord()(TrackBitLocations::kTanlMSB, TrackBitLocations::kTanlLSB); }
0180   z0_t getZ0Word() const { return getTrackWord()(TrackBitLocations::kZ0MSB, TrackBitLocations::kZ0LSB); }
0181   d0_t getD0Word() const { return getTrackWord()(TrackBitLocations::kD0MSB, TrackBitLocations::kD0LSB); }
0182   chi2rphi_t getChi2RPhiWord() const {
0183     return getTrackWord()(TrackBitLocations::kChi2RPhiMSB, TrackBitLocations::kChi2RPhiLSB);
0184   }
0185   chi2rz_t getChi2RZWord() const {
0186     return getTrackWord()(TrackBitLocations::kChi2RZMSB, TrackBitLocations::kChi2RZLSB);
0187   }
0188   bendChi2_t getBendChi2Word() const {
0189     return getTrackWord()(TrackBitLocations::kBendChi2MSB, TrackBitLocations::kBendChi2LSB);
0190   }
0191   hit_t getHitPatternWord() const {
0192     return getTrackWord()(TrackBitLocations::kHitPatternMSB, TrackBitLocations::kHitPatternLSB);
0193   }
0194   qualityMVA_t getMVAQualityWord() const {
0195     return getTrackWord()(TrackBitLocations::kMVAQualityMSB, TrackBitLocations::kMVAQualityLSB);
0196   }
0197   otherMVA_t getMVAOtherWord() const {
0198     return getTrackWord()(TrackBitLocations::kMVAOtherMSB, TrackBitLocations::kMVAOtherLSB);
0199   }
0200   tkword_t getTrackWord() const { return tkword_t(trackWord_.to_string().c_str(), 2); }
0201 
0202   // These functions return the packed bits in unsigned integer format for each quantity
0203   // Signed quantities have the sign enconded in the left-most bit of the pattern using
0204   //   a two's complement representation
0205   unsigned int getValidBits() const { return getValidWord().to_uint(); }
0206   unsigned int getRinvBits() const { return getRinvWord().to_uint(); }
0207   unsigned int getPhiBits() const { return getPhiWord().to_uint(); }
0208   unsigned int getTanlBits() const { return getTanlWord().to_uint(); }
0209   unsigned int getZ0Bits() const { return getZ0Word().to_uint(); }
0210   unsigned int getD0Bits() const { return getD0Word().to_uint(); }
0211   unsigned int getChi2RPhiBits() const { return getChi2RPhiWord().to_uint(); }
0212   unsigned int getChi2RZBits() const { return getChi2RZWord().to_uint(); }
0213   unsigned int getBendChi2Bits() const { return getBendChi2Word().to_uint(); }
0214   unsigned int getHitPatternBits() const { return getHitPatternWord().to_uint(); }
0215   unsigned int getMVAQualityBits() const { return getMVAQualityWord().to_uint(); }
0216   unsigned int getMVAOtherBits() const { return getMVAOtherWord().to_uint(); }
0217 
0218   // These functions return the unpacked and converted values
0219   // These functions return real numbers converted from the digitized quantities by unpacking the 96-bit track word
0220   bool getValid() const { return getValidWord().to_bool(); }
0221   double getRinv() const { return undigitizeSignedValue(getRinvBits(), TrackBitWidths::kRinvSize, stepRinv); }
0222   double getPhi() const { return undigitizeSignedValue(getPhiBits(), TrackBitWidths::kPhiSize, stepPhi0); }
0223   double getTanl() const { return undigitizeSignedValue(getTanlBits(), TrackBitWidths::kTanlSize, stepTanL); }
0224   double getZ0() const { return undigitizeSignedValue(getZ0Bits(), TrackBitWidths::kZ0Size, stepZ0); }
0225   double getD0() const { return undigitizeSignedValue(getD0Bits(), TrackBitWidths::kD0Size, stepD0); }
0226   double getChi2RPhi() const { return chi2RPhiBins[getChi2RPhiBits()]; }
0227   double getChi2RZ() const { return chi2RZBins[getChi2RZBits()]; }
0228   double getBendChi2() const { return bendChi2Bins[getBendChi2Bits()]; }
0229   unsigned int getHitPattern() const { return getHitPatternBits(); }
0230   unsigned int getNStubs() const { return countSetBits(getHitPatternBits()); }
0231   double getMVAQuality() const { return tqMVABins[getMVAQualityBits()]; }
0232   double getMVAOther() const { return getMVAOtherBits(); }
0233 
0234   // ----------member functions (setters) ------------
0235   void setTrackWord(unsigned int valid,
0236                     const GlobalVector& momentum,
0237                     const GlobalPoint& POCA,
0238                     double rInv,
0239                     double chi2RPhi,  // would be total chisq if chi2Z is zero
0240                     double chi2RZ,
0241                     double bendChi2,
0242                     unsigned int hitPattern,
0243                     double mvaQuality,
0244                     double mvaOther,
0245                     unsigned int sector);
0246 
0247   void setTrackWord(unsigned int valid,
0248                     unsigned int rInv,
0249                     unsigned int phi0,  // local phi
0250                     unsigned int tanl,
0251                     unsigned int z0,
0252                     unsigned int d0,
0253                     unsigned int chi2RPhi,  // would be total chisq if chi2Z is zero
0254                     unsigned int chi2RZ,
0255                     unsigned int bendChi2,
0256                     unsigned int hitPattern,
0257                     unsigned int mvaQuality,
0258                     unsigned int mvaOther);
0259 
0260   void setTrackWord(ap_uint<TrackBitWidths::kValidSize> valid,
0261                     ap_uint<TrackBitWidths::kRinvSize> rInv,
0262                     ap_uint<TrackBitWidths::kPhiSize> phi0,  // local phi
0263                     ap_uint<TrackBitWidths::kTanlSize> tanl,
0264                     ap_uint<TrackBitWidths::kZ0Size> z0,
0265                     ap_uint<TrackBitWidths::kD0Size> d0,
0266                     ap_uint<TrackBitWidths::kChi2RPhiSize> chi2RPhi,  // would be total chisq if chi2Z is zero
0267                     ap_uint<TrackBitWidths::kChi2RZSize> chi2RZ,
0268                     ap_uint<TrackBitWidths::kBendChi2Size> bendChi2,
0269                     ap_uint<TrackBitWidths::kHitPatternSize> hitPattern,
0270                     ap_uint<TrackBitWidths::kMVAQualitySize> mvaQuality,
0271                     ap_uint<TrackBitWidths::kMVAOtherSize> mvaOther);
0272 
0273   // ----------member functions (testers) ------------
0274   bool singleDigitizationSchemeTest(const double floatingPointValue, const unsigned int nBits, const double lsb) const;
0275   void testDigitizationScheme() const;
0276 
0277 protected:
0278   // ----------protected member functions ------------
0279   float localPhi(float globalPhi, unsigned int sector) const {
0280     return reco::deltaPhi(globalPhi, (sector * sectorWidth));
0281   }
0282 
0283 public:
0284   // ----------public member functions --------------
0285   unsigned int countSetBits(unsigned int n) const {
0286     // Adapted from: https://www.geeksforgeeks.org/count-set-bits-in-an-integer/
0287     unsigned int count = 0;
0288     while (n) {
0289       n &= (n - 1);
0290       count++;
0291     }
0292     return count;
0293   }
0294 
0295   unsigned int digitizeSignedValue(double value, unsigned int nBits, double lsb) const {
0296     // Digitize the incoming value
0297     int digitizedValue = std::floor(value / lsb);
0298 
0299     // Calculate the maxmum possible positive value given an output of nBits in size
0300     int digitizedMaximum = (1 << (nBits - 1)) - 1;  // The remove 1 bit from nBits to account for the sign
0301     int digitizedMinimum = -1. * (digitizedMaximum + 1);
0302 
0303     // Saturate the digitized value
0304     digitizedValue = std::clamp(digitizedValue, digitizedMinimum, digitizedMaximum);
0305 
0306     // Do the two's compliment encoding
0307     unsigned int twosValue = digitizedValue;
0308     if (digitizedValue < 0) {
0309       twosValue += (1 << nBits);
0310     }
0311 
0312     return twosValue;
0313   }
0314 
0315   template <typename T>
0316   constexpr unsigned int getBin(double value, const T& bins) const {
0317     auto up = std::upper_bound(bins.begin(), bins.end(), value);
0318     return (up - bins.begin() - 1);
0319   }
0320 
0321   double undigitizeSignedValue(unsigned int twosValue, unsigned int nBits, double lsb, double offset = 0.5) const {
0322     // Check that none of the bits above the nBits-1 bit, in a range of [0, nBits-1], are set.
0323     // This makes sure that it isn't possible for the value represented by `twosValue` to be
0324     //  any bigger than ((1 << nBits) - 1).
0325     assert((twosValue >> nBits) == 0);
0326 
0327     // Convert from twos compliment to C++ signed integer (normal digitized value)
0328     int digitizedValue = twosValue;
0329     if (twosValue & (1 << (nBits - 1))) {  // check if the twosValue is negative
0330       digitizedValue -= (1 << nBits);
0331     }
0332 
0333     // Convert to floating point value
0334     return (double(digitizedValue) + offset) * lsb;
0335   }
0336 
0337   // ----------member data ---------------------------
0338   tkword_bs_t trackWord_;
0339 };
0340 
0341 #endif