Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-03-26 02:43:38

0001 // -*- C++ -*-
0002 //
0003 // Package:    L1Trigger/L1TTrackMatch
0004 // Class:      L1GTTInputProducer
0005 //
0006 /**\class L1GTTInputProducer L1GTTInputProducer.cc L1Trigger/L1TTrackMatch/plugins/L1GTTInputProducer.cc
0007 
0008  Description: Takes in L1TTracks and outputs the same tracks, but with modifications to the underlying track word.
0009    The modifications convert from Rinv --> pt and tanL --> eta.
0010 
0011  Implementation:
0012      [Notes on implementation]
0013 */
0014 //
0015 // Original Author:  Alexx Perloff
0016 //         Created:  Sat, 20 Feb 2021 17:02:00 GMT
0017 //
0018 //
0019 
0020 // user include files
0021 #include "DataFormats/Common/interface/Handle.h"
0022 #include "DataFormats/Common/interface/View.h"
0023 #include "DataFormats/L1TrackTrigger/interface/TTTypes.h"
0024 #include "FWCore/Framework/interface/Frameworkfwd.h"
0025 #include "FWCore/Framework/interface/global/EDProducer.h"
0026 #include "FWCore/Framework/interface/Event.h"
0027 #include "FWCore/Framework/interface/MakerMacros.h"
0028 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0029 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0030 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0031 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0032 #include "FWCore/Utilities/interface/EDMException.h"
0033 #include "FWCore/Utilities/interface/StreamID.h"
0034 
0035 // Vivado HLS includes
0036 #include <ap_fixed.h>
0037 #include <ap_int.h>
0038 
0039 // system include files
0040 #define _USE_MATH_DEFINES
0041 #include <cmath>
0042 #include <string>
0043 #include <sstream>
0044 #include <vector>
0045 
0046 //
0047 // class declaration
0048 //
0049 
0050 class L1GTTInputProducer : public edm::global::EDProducer<> {
0051 public:
0052   explicit L1GTTInputProducer(const edm::ParameterSet&);
0053   ~L1GTTInputProducer() override;
0054 
0055   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0056 
0057 private:
0058   // ----------constants, enums and typedefs ---------
0059   static constexpr unsigned int Npars4 = 4;
0060   static constexpr unsigned int Npars5 = 5;
0061   enum ConversionBitWidths {
0062     kEtaMagSize = 3,     // eta output magnitude size; MAG + FRAC should be <= kEtaInputSize
0063     kEtaFracSize = 5,    // eta output fraction size; MAG + FRAC should be <= kEtaInputSize
0064     kEtaInputSize = 16,  // size of tan(lambda)
0065 
0066     kPTMagSize = 7,     // magnitude output size; MAG + FRAC should be <= kPTInputSize
0067     kPTFracSize = 3,    // fraction output size; MAG + FRAC should be <= kPTInputSize
0068     kPTInputSize = 15,  // size of 1/R
0069 
0070     kEtaOutputSize = kEtaMagSize + kEtaFracSize,  // total bit width for eta
0071     kPTOutputSize = kPTMagSize + kPTFracSize,     // total bit width for pT
0072   };
0073 
0074   static constexpr double kEtaErrThresh = 0.0485;  // error corresponding to 0.25 of a degree error in lambda
0075 
0076   static constexpr double kPTErrThresh = 5;                    // error threshold in percent
0077   static constexpr double kSynchrotron = (1.0 / (0.3 * 3.8));  // 1/(0.3*B) for 1/R to 1/pT conversion
0078   static constexpr unsigned int kPtLutSize = (1 << ConversionBitWidths::kPTOutputSize);
0079   static constexpr unsigned int kEtaLutSize = (1 << (ConversionBitWidths::kEtaOutputSize - 1));
0080 
0081   typedef TTTrack<Ref_Phase2TrackerDigi_> L1Track;
0082   typedef std::vector<L1Track> TTTrackCollection;
0083   typedef edm::View<L1Track> TTTrackCollectionView;
0084   typedef ap_fixed<kEtaOutputSize, kEtaMagSize, AP_RND_CONV, AP_SAT> out_eta_t;
0085   typedef TTTrack_TrackWord::tanl_t in_eta_t;
0086   typedef ap_ufixed<kPTOutputSize, kPTMagSize, AP_RND_CONV, AP_SAT> out_pt_t;
0087   typedef TTTrack_TrackWord::rinv_t in_pt_t;
0088   typedef ap_uint<1> out_charge_t;
0089 
0090   // ----------member functions ----------------------
0091   void generate_eta_lut();
0092   void generate_pt_lut();
0093   bool getEtaBits(
0094       const L1Track& track, out_eta_t& etaBits, double& expected, double& maxErrPerc, double& maxErrEpsilon) const;
0095   bool getPtBits(const L1Track& track,
0096                  out_pt_t& ptBits,
0097                  out_charge_t& chargeBit,
0098                  double& expected,
0099                  double& maxErrPerc,
0100                  double& maxErrEpsilon,
0101                  double& minErrPerc,
0102                  double& minExpected) const;
0103   double indexTanLambda2Eta(unsigned int indexTanLambda) const;
0104   double inverseRT2InversePT(unsigned int indexRT) const;
0105   void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
0106   template <typename T>
0107   int sgn(T val) const {
0108     return (T(0) < val) - (val < T(0));
0109   }  // From https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
0110   double unpackSignedValue(unsigned int bits, unsigned int nBits, double lsb) const;
0111 
0112   // ----------member data ---------------------------
0113   const edm::EDGetTokenT<TTTrackCollectionView> l1TracksToken_;
0114   const std::string outputCollectionName_;
0115   int debug_;
0116   std::vector<out_pt_t> pt_lut_;
0117   std::vector<out_eta_t> eta_lut_;
0118 };
0119 
0120 //
0121 // constructors and destructor
0122 //
0123 L1GTTInputProducer::L1GTTInputProducer(const edm::ParameterSet& iConfig)
0124     : l1TracksToken_(consumes<TTTrackCollectionView>(iConfig.getParameter<edm::InputTag>("l1TracksInputTag"))),
0125       outputCollectionName_(iConfig.getParameter<std::string>("outputCollectionName")),
0126       debug_(iConfig.getParameter<int>("debug")) {
0127   // Generate the required luts
0128   generate_eta_lut();
0129   generate_pt_lut();
0130 
0131   // Define EDM output to be written to file (if required)
0132   produces<TTTrackCollection>(outputCollectionName_);
0133   produces<std::vector<double>>("L1GTTInputTrackPtExpected");
0134   produces<std::vector<double>>("L1GTTInputTrackEtaExpected");
0135 }
0136 
0137 L1GTTInputProducer::~L1GTTInputProducer() {}
0138 
0139 //
0140 // member functions
0141 //
0142 
0143 /**
0144   generate_lut: calculate the lut and write it to a file
0145   - argument:None
0146   - return (void): None
0147   - method:
0148     1) iterates through all possibilities of the input value
0149     2) finds values of eta from input values
0150     3) stores the values of eta in an array (lut)
0151     4) writes out the array into a file (eta_lut.h)
0152 */
0153 void L1GTTInputProducer::generate_eta_lut() {
0154   // initialize lut array
0155   eta_lut_.reserve(kEtaLutSize);
0156 
0157   // iterate through all values in the lut
0158   for (unsigned int i = 0; i < kEtaLutSize; i++) {
0159     // -1 to ignore sign bit for input
0160     unsigned int index = ((i + 0.5) * pow(2, (int)(kEtaInputSize - kEtaOutputSize)));
0161     double newValue = indexTanLambda2Eta(index);  // map out the index to the represented eta
0162     out_eta_t out_eta = newValue;                 // cast it to fxp
0163     eta_lut_[i] = out_eta;                        // add value for the lut
0164   }
0165 
0166   if (debug_ >= 3) {
0167     edm::LogInfo log("L1GTTInputProducer");
0168     log << "generate_eta_lut::The eta_lut_[" << kEtaLutSize << "] values are ... \n";
0169     for (unsigned int i = 0; i < kEtaLutSize; i++) {
0170       log << "\t" << i << "\t" << eta_lut_[i] << "\n";
0171     }
0172   }
0173 }
0174 
0175 void L1GTTInputProducer::generate_pt_lut() {
0176   // initialize lut array
0177   pt_lut_.reserve(kPtLutSize);  // generate lut
0178 
0179   // iterate through all values in the lut
0180   for (unsigned int i = 0; i < kPtLutSize; i++) {
0181     unsigned int index = (i + 0.5) * pow(2, (int)(kPTInputSize - 1 - kPTOutputSize));
0182     double newValue = inverseRT2InversePT(index);  //map out the index to the represented 1/pT
0183     out_pt_t out_pt = 1.0 / newValue;              // take the reciprocal and cast as an AP fixed-point (1/pt ==> pt)
0184     pt_lut_[i] = out_pt;                           // setting the i-th value for the lut
0185   }
0186 
0187   if (debug_ >= 3) {
0188     edm::LogInfo log("L1GTTInputProducer");
0189     log << "generate_pt_lut::The pt_lut_[" << kPtLutSize << "] values are ... \n";
0190     for (unsigned int i = 0; i < kPtLutSize; i++) {
0191       log << "\t" << i << "\t" << pt_lut_[i] << "\n";
0192     }
0193   }
0194 }
0195 
0196 double L1GTTInputProducer::unpackSignedValue(unsigned int bits, unsigned int nBits, double lsb) const {
0197   // Check that none of the bits above the nBits-1 bit, in a range of [0, nBits-1], are set.
0198   // This makes sure that it isn't possible for the value represented by 'bits' to be
0199   //  any bigger than ((1 << nBits) - 1).
0200   assert((bits >> nBits) == 0);
0201 
0202   // Convert from twos compliment to C++ signed integer (normal digitized value)
0203   int digitizedValue = bits;
0204   if (bits & (1 << (nBits - 1))) {  // check if the 'bits' is negative
0205     digitizedValue -= (1 << nBits);
0206   }
0207 
0208   // Convert to floating point value
0209   return (double(digitizedValue) + 0.5) * lsb;
0210 }
0211 
0212 /**
0213     indexTanLambda2Eta: calculates eta from tan(lambda)
0214     - argument:
0215         indexTanLambda (int): the index representation for tan(lambda)
0216     - formula:
0217         f(x) = -1*ln(tan((pi/2-atan(x))/2)), where x = tan(lambda)
0218     - return (double): eta
0219 */
0220 double L1GTTInputProducer::indexTanLambda2Eta(unsigned int indexTanLambda) const {
0221   double tanl = unpackSignedValue(indexTanLambda, kEtaInputSize, TTTrack_TrackWord::stepTanL);
0222   double theta = (M_PI / 2.0) - atan(tanl);
0223   double eta = -1.0 * log(tan(theta / 2.0));
0224   if (debug_ >= 3) {
0225     edm::LogInfo("L1GTTInputProducer") << "indexTanLambda2Eta::tanl index = " << indexTanLambda << "\n"
0226                                        << "indexTanLambda2Eta::tanl value = " << tanl << "\n"
0227                                        << "indexTanLambda2Eta::theta = " << theta << "\n"
0228                                        << "indexTanLambda2Eta::eta = " << eta;
0229   }
0230   return eta;
0231 }
0232 
0233 /**
0234   inverseRT2InversePT: calculates 1/pT from 1/rT
0235   - argument:
0236     indexRT (int): the index representation for 1/rT
0237   - formula:
0238       f(x) = 100.*(1/(0.3*3.8))*x , where x = 1/R
0239   - return (double): 1/pT
0240 */
0241 double L1GTTInputProducer::inverseRT2InversePT(unsigned int indexRT) const {
0242   double inverseRT = unpackSignedValue(indexRT, kPTInputSize, TTTrack_TrackWord::stepRinv);
0243   return 100.0 * kSynchrotron * inverseRT;  // multiply by 100 to convert from cm to m
0244 }
0245 
0246 bool L1GTTInputProducer::getEtaBits(
0247     const L1Track& track, out_eta_t& etaBits, double& expected, double& maxErrPerc, double& maxErrEpsilon) const {
0248   // Conver the input to an ap_uint
0249   in_eta_t value = track.getTanlWord();
0250 
0251   // Get the expected outcome (floating point)
0252   out_eta_t maxValuePossible = pow(2, 15);  // saturate at max value possible for fxp
0253   expected = indexTanLambda2Eta(value);     // expected value for eta
0254   if (expected > maxValuePossible) {
0255     expected = maxValuePossible;
0256   }
0257 
0258   // Converted value (emulation)
0259   // Masking and shifting converts the efficient bit representation into an index
0260   // Start by setting up the masks
0261   in_eta_t indexTanLambda = value;
0262   in_eta_t mask = ~0;                                                      // mask (all 1's)
0263   bool sign = indexTanLambda.range(kEtaInputSize - 1, kEtaInputSize - 1);  // sign bit of indexTanLambda
0264   mask *= sign;  // all 0's for positive numbers, all 1's for negative numbers
0265 
0266   // Take the absolute value of indexTanLambda (2's complement)
0267   indexTanLambda ^= mask;
0268   indexTanLambda += sign;
0269 
0270   // Find the value for eta, not |eta|
0271   indexTanLambda =
0272       indexTanLambda >>
0273       (kEtaInputSize -
0274        kEtaOutputSize);  // Don't subtract 1 because we now want to take into account the sign bit of the output
0275   indexTanLambda =
0276       (indexTanLambda < (1 << (kEtaOutputSize - 1))) ? indexTanLambda : in_eta_t((1 << (kEtaOutputSize - 1)) - 1);
0277   etaBits = eta_lut_[indexTanLambda];
0278 
0279   // Reinacting the sign
0280   out_eta_t maskOut;
0281   maskOut.V = ~0;
0282   maskOut *= sign;
0283   etaBits ^= maskOut;
0284   etaBits.V += sign;
0285 
0286   // Compare the floating point calculation to the emulation
0287   double delta = std::abs(expected - etaBits.to_double());
0288   double perc_diff = (delta / std::abs(expected)) * 100.;  // calc percentage error
0289   if (delta > maxErrEpsilon) {
0290     maxErrPerc = perc_diff;
0291     maxErrEpsilon = delta;
0292   }
0293 
0294   if (delta >= kEtaErrThresh) {
0295     edm::LogError("L1GTTInputProducer") << "getEtaBits::MISMATCH!!!\n"
0296                                         << "\tTTTrack tanL = " << track.tanL() << "\n"
0297                                         << "\tTTTrack eta = " << track.momentum().eta() << "\n"
0298                                         << "\tTTTrack_TrackWord = " << track.getTrackWord().to_string(2) << "\n"
0299                                         << "\tTTTrack_TrackWord tanlWord = " << track.getTanlWord() << " ("
0300                                         << track.getTanlWord().to_string(2) << ")\n"
0301                                         << "\tin_eta_t value = " << value << " (" << value.to_string(2) << ")\n"
0302                                         << "\tExpected value = " << expected << "\n"
0303                                         << "\tCalculated eta = " << etaBits.to_double() << " (" << etaBits.to_string(2)
0304                                         << ") @ index " << indexTanLambda << "\n"
0305                                         << "\tDelta = " << delta << "\tpercentage error = " << perc_diff;
0306     return true;
0307   } else {
0308     if (debug_ >= 2) {
0309       edm::LogInfo("L1GTTInputProducer")
0310           << "getEtaBits::SUCCESS (TTTrack, floating eta calculation, bitwise calculation, initial index, lut index) = "
0311           << "(" << track.momentum().eta() << ", " << expected << ", " << etaBits << ", " << value << ", "
0312           << indexTanLambda << ")";
0313     }
0314   }
0315 
0316   return false;
0317 }
0318 
0319 bool L1GTTInputProducer::getPtBits(const L1Track& track,
0320                                    out_pt_t& ptBits,
0321                                    out_charge_t& chargeBit,
0322                                    double& expected,
0323                                    double& maxErrPerc,
0324                                    double& maxErrEpsilon,
0325                                    double& minErrPerc,
0326                                    double& minExpected) const {
0327   // Convert the input to an ap_uint
0328   in_pt_t value = track.getRinvWord();
0329   in_pt_t value_initial = value;
0330 
0331   // Get the expected outcome (floating point)
0332   out_pt_t maxValuePossible = pow(2, 16);       // saturate at max value possible for fxp
0333   expected = 1.0 / inverseRT2InversePT(value);  // expected value for inverse
0334   bool saturation = true;
0335   if (std::abs(expected) > maxValuePossible) {
0336     expected = maxValuePossible;
0337   } else {
0338     saturation = false;
0339   }
0340 
0341   // Converted value (emulation)
0342   // Masking and shifting converts the efficient bit representation into an index
0343   // Start by setting up the masks
0344   in_pt_t mask = ~0;                                            // mask (all 1's)
0345   bool sign = value.range(kPTInputSize - 1, kPTInputSize - 1);  // sign bit of value
0346   mask *= sign;  // all 0's for positive numbers, all 1's for negative numbers
0347 
0348   // Take the absolute value of value (2's complement)
0349   value ^= mask;
0350   value += sign;
0351 
0352   // Shift the value so that the index changes when the LSB of the output changes
0353   value = value >> (kPTInputSize - 1 - (kPTOutputSize));
0354 
0355   // Get the pt from the LUT
0356   ptBits = pt_lut_[value];
0357 
0358   // Set the charge bit
0359   chargeBit = sign;
0360   double charge = 1. - (2 * chargeBit.to_uint());
0361 
0362   // Compare the floating point calculation to the emulation
0363   double delta = std::abs(expected - (charge * ptBits.to_double()));
0364   double perc_diff = (delta / std::abs(expected)) * 100.;
0365 
0366   if (delta > maxErrEpsilon) {
0367     maxErrPerc = perc_diff;
0368     maxErrEpsilon = delta;
0369   } else if (delta < minExpected && !saturation && minErrPerc > 100.0) {
0370     minErrPerc = perc_diff;
0371     minExpected = expected;
0372   }
0373 
0374   if (std::abs(perc_diff) >= kPTErrThresh && !saturation) {
0375     edm::LogError("L1GTTInputProducer") << "getPtBits::MISMATCH!!!\n"
0376                                         << "\tTTTrack Rinv = " << track.rInv() << "\n"
0377                                         << "\tTTTrack pt = " << track.momentum().transverse() << "\n"
0378                                         << "\tTTTrack_TrackWord = " << track.getTrackWord().to_string(2) << "\n"
0379                                         << "\tTTTrack_TrackWord RinvWord = " << track.getRinvWord() << " ("
0380                                         << track.getRinvWord().to_string(2) << ")\n"
0381                                         << "\tin_pt_t value = " << value_initial << " (" << value_initial.to_string(2)
0382                                         << ")\n"
0383                                         << "\tExpected value = " << expected << "\n"
0384                                         << "\tCalculated pt = " << ptBits.to_double() << " (" << ptBits.to_string(2)
0385                                         << ") @ index " << value << "\n"
0386                                         << "\tcharge = " << charge << " (bit = " << chargeBit << ")\n"
0387                                         << "\tDelta = " << delta << "\tpercentage error = " << perc_diff;
0388     return true;
0389   } else {
0390     if (debug_ >= 2) {
0391       edm::LogInfo("L1GTTInputProducer") << "getPtBits::SUCCESS (TTTrack, floating pt calculation, charge, bitwise "
0392                                             "calculation, initial index, lut index) = "
0393                                          << "(" << sgn(track.rInv()) * track.momentum().transverse() << ", " << expected
0394                                          << ", " << charge << ", " << ptBits << ", " << value_initial << ", " << value
0395                                          << ")";
0396     }
0397   }
0398 
0399   return false;
0400 }
0401 
0402 // ------------ method called to produce the data  ------------
0403 void L1GTTInputProducer::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
0404   auto vTTTrackOutput = std::make_unique<TTTrackCollection>();
0405   auto vPtOutput = std::make_unique<std::vector<double>>();
0406   auto vEtaOutput = std::make_unique<std::vector<double>>();
0407 
0408   edm::Handle<TTTrackCollectionView> l1TracksHandle;
0409   iEvent.getByToken(l1TracksToken_, l1TracksHandle);
0410 
0411   out_charge_t chargeBit = 0;
0412   out_pt_t ptBits = 0;
0413   out_eta_t etaBits = 0;
0414   in_pt_t ptBitsShifted = 0;
0415   in_eta_t etaBitsShifted = 0;
0416   unsigned int error_pt_c = 0;        // error counter
0417   unsigned int error_eta_c = 0;       // error counter
0418   double expectedPt = 0.0;            // expected value of the pt
0419   double expectedEta = 0.0;           // expected value of the eta
0420   double maxErrPercPt = 0.0;          // stores the maximum error percentage
0421   double maxErrPercEta = 0.0;         // stores the maximum error percentage
0422   double maxErrEpsilonPt = 0.0;       // keeps track of epsilon for max error
0423   double maxErrEpsilonEta = 0.0;      // keeps track of epsilon for max error
0424   double minErrPercPt = 10000000.0;   // stores the maximum error percentage
0425   double minExpectedPt = 10000000.0;  // keeps track of epsilon for max error
0426 
0427   unsigned int nOutput = l1TracksHandle->size();
0428   vTTTrackOutput->reserve(nOutput);
0429   vPtOutput->reserve(nOutput);
0430   vEtaOutput->reserve(nOutput);
0431   for (const auto& track : *l1TracksHandle) {
0432     if (!(track.nFitPars() == Npars4 || track.nFitPars() == Npars5)) {
0433       throw cms::Exception("nFitPars unknown")
0434           << "L1GTTInputProducer::produce method is called with numFitPars_ = " << track.nFitPars()
0435           << ". The only possible values are 4/5.";
0436     }
0437 
0438     // Fill the vector of tracks
0439     vTTTrackOutput->push_back(track);
0440     auto& currentTrackRef = vTTTrackOutput->back();
0441     if (debug_ >= 2) {
0442       edm::LogInfo("L1GTTInputProducer") << "produce::word before anything "
0443                                          << currentTrackRef.getTrackWord().to_string(2);
0444     }
0445 
0446     // Do an initial setting of the bits based on the floating point values
0447     currentTrackRef.setTrackWordBits();
0448     if (debug_ >= 2) {
0449       edm::LogInfo("L1GTTInputProducer") << "produce::word after initial setting of the track word "
0450                                          << currentTrackRef.getTrackWord().to_string(2);
0451     }
0452 
0453     // Do the conversions
0454     error_pt_c += getPtBits(
0455         currentTrackRef, ptBits, chargeBit, expectedPt, maxErrPercPt, maxErrEpsilonPt, minErrPercPt, minExpectedPt);
0456     error_eta_c += getEtaBits(currentTrackRef, etaBits, expectedEta, maxErrPercEta, maxErrEpsilonEta);
0457 
0458     // Assign the exat same bits to an ap_uint
0459     ptBitsShifted = ptBits.range();
0460     etaBitsShifted = etaBits.range();
0461 
0462     // Shift the bits so that the decimal is in the right spot for the GTT software
0463     ptBitsShifted = ptBitsShifted << 2;
0464     etaBitsShifted = etaBitsShifted << 8;
0465 
0466     // Set the MSB for the pt to the sign of the incoming word
0467     ptBitsShifted.set(kPTInputSize - 1, chargeBit);
0468 
0469     // Set the correct bits based on the converted quanteties and the existing track word components
0470     currentTrackRef.setTrackWord(currentTrackRef.getValidWord(),
0471                                  ptBitsShifted,
0472                                  currentTrackRef.getPhiWord(),
0473                                  etaBitsShifted,
0474                                  currentTrackRef.getZ0Word(),
0475                                  currentTrackRef.getD0Word(),
0476                                  currentTrackRef.getChi2RPhiWord(),
0477                                  currentTrackRef.getChi2RZWord(),
0478                                  currentTrackRef.getBendChi2Word(),
0479                                  currentTrackRef.getHitPatternWord(),
0480                                  currentTrackRef.getMVAQualityWord(),
0481                                  currentTrackRef.getMVAOtherWord());
0482     if (debug_ >= 2) {
0483       edm::LogInfo("L1GTTInputProducer") << "produce::charge after all conversions " << chargeBit << "\n"
0484                                          << "produce::ptBits after all conversions " << ptBits.to_string(2) << " ("
0485                                          << ptBitsShifted.to_string(2) << " = " << ptBitsShifted.to_uint() << ")\n"
0486                                          << "produce::etaBits after all conversions " << etaBits.to_string(2) << " ("
0487                                          << etaBitsShifted.to_string(2) << " = " << etaBitsShifted.to_uint() << ")\n"
0488                                          << "produce::word after all conversions "
0489                                          << vTTTrackOutput->back().getTrackWord().to_string(2);
0490     }
0491 
0492     // Fill the remaining outputs
0493     vPtOutput->push_back(expectedPt);
0494     vEtaOutput->push_back(expectedEta);
0495   }
0496 
0497   if (debug_ >= 1) {
0498     edm::LogInfo("L1GTTInputProducer") << "\nNumber of converted tracks: " << nOutput << "\n\n"
0499                                        << "q/r ==> pt conversion:\n"
0500                                        << "\tError Threshold: " << kPTErrThresh << "%\n"
0501                                        << "\tMax error: " << maxErrEpsilonPt
0502                                        << " GeV difference with percentage: " << maxErrPercPt << "% @ "
0503                                        << 100.0 * maxErrEpsilonPt / maxErrPercPt << " GeV"
0504                                        << "\n"
0505                                        << "\tError @ max range: " << minExpectedPt
0506                                        << " GeV with precentage: " << minErrPercPt << "%"
0507                                        << "\n"
0508                                        << "\tTotal number of errors: " << error_pt_c << "\n\n"
0509                                        << "tan(lambda) ==> eta conversion:\n"
0510                                        << "\tError Threshold: " << kEtaErrThresh << "\n"
0511                                        << "\tMax error: " << maxErrEpsilonEta << " with percentage: " << maxErrPercEta
0512                                        << "% @ " << 100.0 * maxErrEpsilonEta / maxErrPercEta << "\n"
0513                                        << "\tTotal number of errors: " << error_eta_c;
0514   }
0515 
0516   if (error_pt_c + error_eta_c) {
0517     edm::LogError("L1GTTInputProducer") << "produce::" << error_pt_c << "/" << error_eta_c
0518                                         << " pt/eta mismatches detected!!!";
0519   }
0520 
0521   // Put the outputs into the event
0522   iEvent.put(std::move(vTTTrackOutput), outputCollectionName_);
0523   iEvent.put(std::move(vPtOutput), "L1GTTInputTrackPtExpected");
0524   iEvent.put(std::move(vEtaOutput), "L1GTTInputTrackEtaExpected");
0525 }
0526 
0527 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0528 void L1GTTInputProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0529   // L1GTTInputProducer
0530   edm::ParameterSetDescription desc;
0531   desc.add<int>("debug", 0)->setComment("Verbosity levels: 0, 1, 2, 3");
0532   desc.add<edm::InputTag>("l1TracksInputTag", edm::InputTag("TTTracksFromTrackletEmulation", "Level1TTTracks"));
0533   desc.add<std::string>("outputCollectionName", "Level1TTTracksConverted");
0534   descriptions.addWithDefaultLabel(desc);
0535 }
0536 
0537 //define this as a plug-in
0538 DEFINE_FWK_MODULE(L1GTTInputProducer);