Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:16

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   bool setTrackWordBits_;
0116   int debug_;
0117   std::vector<out_pt_t> pt_lut_;
0118   std::vector<out_eta_t> eta_lut_;
0119 };
0120 
0121 //
0122 // constructors and destructor
0123 //
0124 L1GTTInputProducer::L1GTTInputProducer(const edm::ParameterSet& iConfig)
0125     : l1TracksToken_(consumes<TTTrackCollectionView>(iConfig.getParameter<edm::InputTag>("l1TracksInputTag"))),
0126       outputCollectionName_(iConfig.getParameter<std::string>("outputCollectionName")),
0127       setTrackWordBits_(iConfig.getParameter<bool>("setTrackWordBits")),
0128       debug_(iConfig.getParameter<int>("debug")) {
0129   // Generate the required luts
0130   generate_eta_lut();
0131   generate_pt_lut();
0132 
0133   // Define EDM output to be written to file (if required)
0134   produces<TTTrackCollection>(outputCollectionName_);
0135   produces<std::vector<double>>("L1GTTInputTrackPtExpected");
0136   produces<std::vector<double>>("L1GTTInputTrackEtaExpected");
0137 }
0138 
0139 L1GTTInputProducer::~L1GTTInputProducer() {}
0140 
0141 //
0142 // member functions
0143 //
0144 
0145 /**
0146   generate_lut: calculate the lut and write it to a file
0147   - argument:None
0148   - return (void): None
0149   - method:
0150     1) iterates through all possibilities of the input value
0151     2) finds values of eta from input values
0152     3) stores the values of eta in an array (lut)
0153     4) writes out the array into a file (eta_lut.h)
0154 */
0155 void L1GTTInputProducer::generate_eta_lut() {
0156   // initialize lut array
0157   eta_lut_.reserve(kEtaLutSize);
0158 
0159   // iterate through all values in the lut
0160   for (unsigned int i = 0; i < kEtaLutSize; i++) {
0161     // -1 to ignore sign bit for input
0162     unsigned int index = ((i + 0.5) * pow(2, (int)(kEtaInputSize - kEtaOutputSize)));
0163     double newValue = indexTanLambda2Eta(index);  // map out the index to the represented eta
0164     out_eta_t out_eta = newValue;                 // cast it to fxp
0165     eta_lut_[i] = out_eta;                        // add value for the lut
0166   }
0167 
0168   if (debug_ >= 3) {
0169     edm::LogInfo log("L1GTTInputProducer");
0170     log << "generate_eta_lut::The eta_lut_[" << kEtaLutSize << "] values are ... \n";
0171     for (unsigned int i = 0; i < kEtaLutSize; i++) {
0172       log << "\t" << i << "\t" << eta_lut_[i] << "\n";
0173     }
0174   }
0175 }
0176 
0177 void L1GTTInputProducer::generate_pt_lut() {
0178   // initialize lut array
0179   pt_lut_.reserve(kPtLutSize);  // generate lut
0180 
0181   // iterate through all values in the lut
0182   for (unsigned int i = 0; i < kPtLutSize; i++) {
0183     unsigned int index = (i + 0.5) * pow(2, (int)(kPTInputSize - 1 - kPTOutputSize));
0184     double newValue = inverseRT2InversePT(index);  //map out the index to the represented 1/pT
0185     out_pt_t out_pt = 1.0 / newValue;              // take the reciprocal and cast as an AP fixed-point (1/pt ==> pt)
0186     pt_lut_[i] = out_pt;                           // setting the i-th value for the lut
0187   }
0188 
0189   if (debug_ >= 3) {
0190     edm::LogInfo log("L1GTTInputProducer");
0191     log << "generate_pt_lut::The pt_lut_[" << kPtLutSize << "] values are ... \n";
0192     for (unsigned int i = 0; i < kPtLutSize; i++) {
0193       log << "\t" << i << "\t" << pt_lut_[i] << "\n";
0194     }
0195   }
0196 }
0197 
0198 double L1GTTInputProducer::unpackSignedValue(unsigned int bits, unsigned int nBits, double lsb) const {
0199   // Check that none of the bits above the nBits-1 bit, in a range of [0, nBits-1], are set.
0200   // This makes sure that it isn't possible for the value represented by 'bits' to be
0201   //  any bigger than ((1 << nBits) - 1).
0202   assert((bits >> nBits) == 0);
0203 
0204   // Convert from twos compliment to C++ signed integer (normal digitized value)
0205   int digitizedValue = bits;
0206   if (bits & (1 << (nBits - 1))) {  // check if the 'bits' is negative
0207     digitizedValue -= (1 << nBits);
0208   }
0209 
0210   // Convert to floating point value
0211   return (double(digitizedValue) + 0.5) * lsb;
0212 }
0213 
0214 /**
0215     indexTanLambda2Eta: calculates eta from tan(lambda)
0216     - argument:
0217         indexTanLambda (int): the index representation for tan(lambda)
0218     - formula:
0219         f(x) = -1*ln(tan((pi/2-atan(x))/2)), where x = tan(lambda)
0220     - return (double): eta
0221 */
0222 double L1GTTInputProducer::indexTanLambda2Eta(unsigned int indexTanLambda) const {
0223   double tanl = unpackSignedValue(indexTanLambda, kEtaInputSize, TTTrack_TrackWord::stepTanL);
0224   double theta = (M_PI / 2.0) - atan(tanl);
0225   double eta = -1.0 * log(tan(theta / 2.0));
0226   if (debug_ >= 3) {
0227     edm::LogInfo("L1GTTInputProducer") << "indexTanLambda2Eta::tanl index = " << indexTanLambda << "\n"
0228                                        << "indexTanLambda2Eta::tanl value = " << tanl << "\n"
0229                                        << "indexTanLambda2Eta::theta = " << theta << "\n"
0230                                        << "indexTanLambda2Eta::eta = " << eta;
0231   }
0232   return eta;
0233 }
0234 
0235 /**
0236   inverseRT2InversePT: calculates 1/pT from 1/rT
0237   - argument:
0238     indexRT (int): the index representation for 1/rT
0239   - formula:
0240       f(x) = 100.*(1/(0.3*3.8))*x , where x = 1/R
0241   - return (double): 1/pT
0242 */
0243 double L1GTTInputProducer::inverseRT2InversePT(unsigned int indexRT) const {
0244   double inverseRT = unpackSignedValue(indexRT, kPTInputSize, TTTrack_TrackWord::stepRinv);
0245   return 100.0 * kSynchrotron * inverseRT;  // multiply by 100 to convert from cm to m
0246 }
0247 
0248 bool L1GTTInputProducer::getEtaBits(
0249     const L1Track& track, out_eta_t& etaBits, double& expected, double& maxErrPerc, double& maxErrEpsilon) const {
0250   // Conver the input to an ap_uint
0251   in_eta_t value = track.getTanlWord();
0252 
0253   // Get the expected outcome (floating point)
0254   out_eta_t maxValuePossible = pow(2, 15);  // saturate at max value possible for fxp
0255   expected = indexTanLambda2Eta(value);     // expected value for eta
0256   if (expected > maxValuePossible) {
0257     expected = maxValuePossible;
0258   }
0259 
0260   // Converted value (emulation)
0261   // Masking and shifting converts the efficient bit representation into an index
0262   // Start by setting up the masks
0263   in_eta_t indexTanLambda = value;
0264   in_eta_t mask = ~0;                                                      // mask (all 1's)
0265   bool sign = indexTanLambda.range(kEtaInputSize - 1, kEtaInputSize - 1);  // sign bit of indexTanLambda
0266   mask *= sign;  // all 0's for positive numbers, all 1's for negative numbers
0267 
0268   // Take the absolute value of indexTanLambda (2's complement)
0269   indexTanLambda ^= mask;
0270   indexTanLambda += sign;
0271 
0272   // Find the value for eta, not |eta|
0273   indexTanLambda =
0274       indexTanLambda >>
0275       (kEtaInputSize -
0276        kEtaOutputSize);  // Don't subtract 1 because we now want to take into account the sign bit of the output
0277   indexTanLambda =
0278       (indexTanLambda < (1 << (kEtaOutputSize - 1))) ? indexTanLambda : in_eta_t((1 << (kEtaOutputSize - 1)) - 1);
0279   etaBits = eta_lut_[indexTanLambda];
0280 
0281   // Reinacting the sign
0282   out_eta_t maskOut;
0283   maskOut.V = ~0;
0284   maskOut *= sign;
0285   etaBits ^= maskOut;
0286   etaBits.V += sign;
0287 
0288   // Compare the floating point calculation to the emulation
0289   double delta = std::abs(expected - etaBits.to_double());
0290   double perc_diff = (delta / std::abs(expected)) * 100.;  // calc percentage error
0291   if (delta > maxErrEpsilon) {
0292     maxErrPerc = perc_diff;
0293     maxErrEpsilon = delta;
0294   }
0295 
0296   if (delta >= kEtaErrThresh) {
0297     edm::LogError("L1GTTInputProducer") << "getEtaBits::MISMATCH!!!\n"
0298                                         << "\tTTTrack tanL = " << track.tanL() << "\n"
0299                                         << "\tTTTrack eta = " << track.momentum().eta() << "\n"
0300                                         << "\tTTTrack_TrackWord = " << track.getTrackWord().to_string(2) << "\n"
0301                                         << "\tTTTrack_TrackWord tanlWord = " << track.getTanlWord() << " ("
0302                                         << track.getTanlWord().to_string(2) << ")\n"
0303                                         << "\tin_eta_t value = " << value << " (" << value.to_string(2) << ")\n"
0304                                         << "\tExpected value = " << expected << "\n"
0305                                         << "\tCalculated eta = " << etaBits.to_double() << " (" << etaBits.to_string(2)
0306                                         << ") @ index " << indexTanLambda << "\n"
0307                                         << "\tDelta = " << delta << "\tpercentage error = " << perc_diff;
0308     return true;
0309   } else {
0310     if (debug_ >= 2) {
0311       edm::LogInfo("L1GTTInputProducer")
0312           << "getEtaBits::SUCCESS (TTTrack, floating eta calculation, bitwise calculation, initial index, lut index) = "
0313           << "(" << track.momentum().eta() << ", " << expected << ", " << etaBits << ", " << value << ", "
0314           << indexTanLambda << ")";
0315     }
0316   }
0317 
0318   return false;
0319 }
0320 
0321 bool L1GTTInputProducer::getPtBits(const L1Track& track,
0322                                    out_pt_t& ptBits,
0323                                    out_charge_t& chargeBit,
0324                                    double& expected,
0325                                    double& maxErrPerc,
0326                                    double& maxErrEpsilon,
0327                                    double& minErrPerc,
0328                                    double& minExpected) const {
0329   // Convert the input to an ap_uint
0330   in_pt_t value = track.getRinvWord();
0331   in_pt_t value_initial = value;
0332 
0333   // Get the expected outcome (floating point)
0334   out_pt_t maxValuePossible = pow(2, 16);       // saturate at max value possible for fxp
0335   expected = 1.0 / inverseRT2InversePT(value);  // expected value for inverse
0336   bool saturation = true;
0337   if (std::abs(expected) > maxValuePossible) {
0338     expected = maxValuePossible;
0339   } else {
0340     saturation = false;
0341   }
0342 
0343   // Converted value (emulation)
0344   // Masking and shifting converts the efficient bit representation into an index
0345   // Start by setting up the masks
0346   in_pt_t mask = ~0;                                            // mask (all 1's)
0347   bool sign = value.range(kPTInputSize - 1, kPTInputSize - 1);  // sign bit of value
0348   mask *= sign;  // all 0's for positive numbers, all 1's for negative numbers
0349 
0350   // Take the absolute value of value (2's complement)
0351   value ^= mask;
0352   value += sign;
0353 
0354   // Shift the value so that the index changes when the LSB of the output changes
0355   value = value >> (kPTInputSize - 1 - (kPTOutputSize));
0356 
0357   // Get the pt from the LUT
0358   ptBits = pt_lut_[value];
0359 
0360   // Set the charge bit
0361   chargeBit = sign;
0362   double charge = 1. - (2 * chargeBit.to_uint());
0363 
0364   // Compare the floating point calculation to the emulation
0365   double delta = std::abs(expected - (charge * ptBits.to_double()));
0366   double perc_diff = (delta / std::abs(expected)) * 100.;
0367 
0368   if (delta > maxErrEpsilon) {
0369     maxErrPerc = perc_diff;
0370     maxErrEpsilon = delta;
0371   } else if (delta < minExpected && !saturation && minErrPerc > 100.0) {
0372     minErrPerc = perc_diff;
0373     minExpected = expected;
0374   }
0375 
0376   if (std::abs(perc_diff) >= kPTErrThresh && !saturation) {
0377     edm::LogError("L1GTTInputProducer") << "getPtBits::MISMATCH!!!\n"
0378                                         << "\tTTTrack Rinv = " << track.rInv() << "\n"
0379                                         << "\tTTTrack pt = " << track.momentum().transverse() << "\n"
0380                                         << "\tTTTrack_TrackWord = " << track.getTrackWord().to_string(2) << "\n"
0381                                         << "\tTTTrack_TrackWord RinvWord = " << track.getRinvWord() << " ("
0382                                         << track.getRinvWord().to_string(2) << ")\n"
0383                                         << "\tin_pt_t value = " << value_initial << " (" << value_initial.to_string(2)
0384                                         << ")\n"
0385                                         << "\tExpected value = " << expected << "\n"
0386                                         << "\tCalculated pt = " << ptBits.to_double() << " (" << ptBits.to_string(2)
0387                                         << ") @ index " << value << "\n"
0388                                         << "\tcharge = " << charge << " (bit = " << chargeBit << ")\n"
0389                                         << "\tDelta = " << delta << "\tpercentage error = " << perc_diff;
0390     return true;
0391   } else {
0392     if (debug_ >= 2) {
0393       edm::LogInfo("L1GTTInputProducer") << "getPtBits::SUCCESS (TTTrack, floating pt calculation, charge, bitwise "
0394                                             "calculation, initial index, lut index) = "
0395                                          << "(" << sgn(track.rInv()) * track.momentum().transverse() << ", " << expected
0396                                          << ", " << charge << ", " << ptBits << ", " << value_initial << ", " << value
0397                                          << ")";
0398     }
0399   }
0400 
0401   return false;
0402 }
0403 
0404 // ------------ method called to produce the data  ------------
0405 void L1GTTInputProducer::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
0406   auto vTTTrackOutput = std::make_unique<TTTrackCollection>();
0407   auto vPtOutput = std::make_unique<std::vector<double>>();
0408   auto vEtaOutput = std::make_unique<std::vector<double>>();
0409 
0410   edm::Handle<TTTrackCollectionView> l1TracksHandle;
0411   iEvent.getByToken(l1TracksToken_, l1TracksHandle);
0412 
0413   out_charge_t chargeBit = 0;
0414   out_pt_t ptBits = 0;
0415   out_eta_t etaBits = 0;
0416   in_pt_t ptBitsShifted = 0;
0417   in_eta_t etaBitsShifted = 0;
0418   unsigned int error_pt_c = 0;        // error counter
0419   unsigned int error_eta_c = 0;       // error counter
0420   double expectedPt = 0.0;            // expected value of the pt
0421   double expectedEta = 0.0;           // expected value of the eta
0422   double maxErrPercPt = 0.0;          // stores the maximum error percentage
0423   double maxErrPercEta = 0.0;         // stores the maximum error percentage
0424   double maxErrEpsilonPt = 0.0;       // keeps track of epsilon for max error
0425   double maxErrEpsilonEta = 0.0;      // keeps track of epsilon for max error
0426   double minErrPercPt = 10000000.0;   // stores the maximum error percentage
0427   double minExpectedPt = 10000000.0;  // keeps track of epsilon for max error
0428 
0429   unsigned int nOutput = l1TracksHandle->size();
0430   vTTTrackOutput->reserve(nOutput);
0431   vPtOutput->reserve(nOutput);
0432   vEtaOutput->reserve(nOutput);
0433   for (const auto& track : *l1TracksHandle) {
0434     if (setTrackWordBits_ && !(track.nFitPars() == Npars4 || track.nFitPars() == Npars5)) {
0435       throw cms::Exception("nFitPars unknown")
0436           << "L1GTTInputProducer::produce method is called with numFitPars_ = " << track.nFitPars()
0437           << ". The only possible values are 4/5.";
0438     }
0439 
0440     // Fill the vector of tracks
0441     vTTTrackOutput->push_back(track);
0442     auto& currentTrackRef = vTTTrackOutput->back();
0443     if (debug_ >= 2) {
0444       edm::LogInfo("L1GTTInputProducer") << "produce::word before anything with setTrackWordBits_ = "
0445                                          << setTrackWordBits_ << ": " << currentTrackRef.getTrackWord().to_string(2);
0446     }
0447 
0448     // Do an initial setting of the bits based on the floating point values
0449     if (setTrackWordBits_)
0450       currentTrackRef.setTrackWordBits();
0451     if (debug_ >= 2) {
0452       edm::LogInfo("L1GTTInputProducer") << "produce::word after initial setting of the track word "
0453                                          << currentTrackRef.getTrackWord().to_string(2);
0454     }
0455 
0456     // Do the conversions
0457     error_pt_c += getPtBits(
0458         currentTrackRef, ptBits, chargeBit, expectedPt, maxErrPercPt, maxErrEpsilonPt, minErrPercPt, minExpectedPt);
0459     error_eta_c += getEtaBits(currentTrackRef, etaBits, expectedEta, maxErrPercEta, maxErrEpsilonEta);
0460 
0461     // Assign the exat same bits to an ap_uint
0462     ptBitsShifted = ptBits.range();
0463     etaBitsShifted = etaBits.range();
0464 
0465     // Shift the bits so that the decimal is in the right spot for the GTT software
0466     ptBitsShifted = ptBitsShifted << 2;
0467     etaBitsShifted = etaBitsShifted << 8;
0468 
0469     // Set the MSB for the pt to the sign of the incoming word
0470     ptBitsShifted.set(kPTInputSize - 1, chargeBit);
0471 
0472     // Set the correct bits based on the converted quanteties and the existing track word components
0473     currentTrackRef.setTrackWord(currentTrackRef.getValidWord(),
0474                                  ptBitsShifted,
0475                                  currentTrackRef.getPhiWord(),
0476                                  etaBitsShifted,
0477                                  currentTrackRef.getZ0Word(),
0478                                  currentTrackRef.getD0Word(),
0479                                  currentTrackRef.getChi2RPhiWord(),
0480                                  currentTrackRef.getChi2RZWord(),
0481                                  currentTrackRef.getBendChi2Word(),
0482                                  currentTrackRef.getHitPatternWord(),
0483                                  currentTrackRef.getMVAQualityWord(),
0484                                  currentTrackRef.getMVAOtherWord());
0485     if (debug_ >= 2) {
0486       edm::LogInfo("L1GTTInputProducer") << "produce::charge after all conversions " << chargeBit << "\n"
0487                                          << "produce::ptBits after all conversions " << ptBits.to_string(2) << " ("
0488                                          << ptBitsShifted.to_string(2) << " = " << ptBitsShifted.to_uint() << ")\n"
0489                                          << "produce::etaBits after all conversions " << etaBits.to_string(2) << " ("
0490                                          << etaBitsShifted.to_string(2) << " = " << etaBitsShifted.to_uint() << ")\n"
0491                                          << "produce::word after all conversions "
0492                                          << vTTTrackOutput->back().getTrackWord().to_string(2);
0493     }
0494 
0495     // Fill the remaining outputs
0496     vPtOutput->push_back(expectedPt);
0497     vEtaOutput->push_back(expectedEta);
0498   }
0499 
0500   if (debug_ >= 1) {
0501     edm::LogInfo("L1GTTInputProducer") << "\nNumber of converted tracks: " << nOutput << "\n\n"
0502                                        << "q/r ==> pt conversion:\n"
0503                                        << "\tError Threshold: " << kPTErrThresh << "%\n"
0504                                        << "\tMax error: " << maxErrEpsilonPt
0505                                        << " GeV difference with percentage: " << maxErrPercPt << "% @ "
0506                                        << 100.0 * maxErrEpsilonPt / maxErrPercPt << " GeV"
0507                                        << "\n"
0508                                        << "\tError @ max range: " << minExpectedPt
0509                                        << " GeV with precentage: " << minErrPercPt << "%"
0510                                        << "\n"
0511                                        << "\tTotal number of errors: " << error_pt_c << "\n\n"
0512                                        << "tan(lambda) ==> eta conversion:\n"
0513                                        << "\tError Threshold: " << kEtaErrThresh << "\n"
0514                                        << "\tMax error: " << maxErrEpsilonEta << " with percentage: " << maxErrPercEta
0515                                        << "% @ " << 100.0 * maxErrEpsilonEta / maxErrPercEta << "\n"
0516                                        << "\tTotal number of errors: " << error_eta_c;
0517   }
0518 
0519   if (error_pt_c + error_eta_c) {
0520     edm::LogError("L1GTTInputProducer") << "produce::" << error_pt_c << "/" << error_eta_c
0521                                         << " pt/eta mismatches detected!!!";
0522   }
0523 
0524   // Put the outputs into the event
0525   iEvent.put(std::move(vTTTrackOutput), outputCollectionName_);
0526   iEvent.put(std::move(vPtOutput), "L1GTTInputTrackPtExpected");
0527   iEvent.put(std::move(vEtaOutput), "L1GTTInputTrackEtaExpected");
0528 }
0529 
0530 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0531 void L1GTTInputProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0532   // L1GTTInputProducer
0533   edm::ParameterSetDescription desc;
0534   desc.add<int>("debug", 0)->setComment("Verbosity levels: 0, 1, 2, 3");
0535   desc.add<edm::InputTag>("l1TracksInputTag", edm::InputTag("TTTracksFromTrackletEmulation", "Level1TTTracks"));
0536   desc.add<std::string>("outputCollectionName", "Level1TTTracksConverted");
0537   desc.add<bool>("setTrackWordBits", true)
0538       ->setComment(
0539           "flag indicated whether the TTTrack_TrackWord should be set from float parameters or skipped (if TrackWord "
0540           "set by e.g. GTTFileReader decoding)");
0541   descriptions.addWithDefaultLabel(desc);
0542 }
0543 
0544 //define this as a plug-in
0545 DEFINE_FWK_MODULE(L1GTTInputProducer);