Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:37:03

0001 // -*- C++ -*-
0002 //
0003 // Package:    L1Trigger/L1TTrackMatch
0004 // Class:      L1TrackVertexAssociationProducer
0005 //
0006 /**\class L1TrackVertexAssociationProducer L1TrackVertexAssociationProducer.cc L1Trigger/L1TTrackMatch/plugins/L1TrackVertexAssociationProducer.cc
0007 
0008  Description: Selects a set of L1Tracks based on a set of predefined criteria.
0009 
0010  Implementation:
0011      Inputs:
0012          std::vector<TTTrack> - Each floating point TTTrack inside this collection inherits from
0013                                 a bit-accurate TTTrack_TrackWord, used for emulation purposes.
0014      Outputs:
0015          std::vector<TTTrackRef> - A collection of TTTrack Refs selected from cuts on the TTTrack properties
0016          std::vector<TTTrackRef> - A collection of TTTrack Refs selected from cuts on the TTTrack_TrackWord properties
0017 */
0018 //
0019 // Original Author:  Alexx Perloff
0020 //         Created:  Thu, 16 Dec 2021 19:02:50 GMT
0021 // Derivative Author: Nick Manganelli
0022 //         Created: Thu, 14 Oct 2023 16:32:32 GMT
0023 //
0024 //
0025 
0026 // system include files
0027 #include <algorithm>
0028 #include <memory>
0029 #include <string>
0030 #include <vector>
0031 
0032 // Xilinx HLS includes
0033 #include <ap_fixed.h>
0034 #include <ap_int.h>
0035 
0036 // user include files
0037 #include "DataFormats/Common/interface/Handle.h"
0038 #include "DataFormats/Common/interface/Ref.h"
0039 #include "DataFormats/Common/interface/RefVector.h"
0040 #include "DataFormats/Common/interface/RefToPtr.h"
0041 #include "DataFormats/Common/interface/Ptr.h"
0042 #include "DataFormats/L1TrackTrigger/interface/TTTypes.h"
0043 #include "DataFormats/L1Trigger/interface/Vertex.h"
0044 #include "DataFormats/L1Trigger/interface/VertexWord.h"
0045 #include "L1Trigger/VertexFinder/interface/L1Track.h"
0046 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0047 #include "CommonTools/Utils/interface/AndSelector.h"
0048 #include "CommonTools/Utils/interface/EtaRangeSelector.h"
0049 #include "CommonTools/Utils/interface/MinSelector.h"
0050 #include "CommonTools/Utils/interface/MinFunctionSelector.h"
0051 #include "CommonTools/Utils/interface/MinNumberSelector.h"
0052 #include "CommonTools/Utils/interface/PtMinSelector.h"
0053 #include "CommonTools/Utils/interface/Selection.h"
0054 #include "FWCore/Framework/interface/Frameworkfwd.h"
0055 #include "FWCore/Framework/interface/global/EDProducer.h"
0056 #include "FWCore/Framework/interface/Event.h"
0057 #include "FWCore/Framework/interface/MakerMacros.h"
0058 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0059 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0060 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0061 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0062 #include "FWCore/Utilities/interface/EDMException.h"
0063 #include "FWCore/Utilities/interface/StreamID.h"
0064 #include "Geometry/Records/interface/TrackerTopologyRcd.h"
0065 #include "PhysicsTools/TensorFlow/interface/TensorFlow.h"
0066 #include "L1Trigger/DemonstratorTools/interface/codecs/tracks.h"
0067 #include "FWCore/ParameterSet/interface/FileInPath.h"
0068 
0069 //
0070 // class declaration
0071 //
0072 
0073 class L1TrackVertexAssociationProducer : public edm::global::EDProducer<> {
0074 public:
0075   explicit L1TrackVertexAssociationProducer(const edm::ParameterSet&);
0076   ~L1TrackVertexAssociationProducer() override;
0077 
0078   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0079 
0080 private:
0081   // ----------constants, enums and typedefs ---------
0082   // Relevant constants for the converted track word
0083   enum TrackBitWidths {
0084     kPtSize = TTTrack_TrackWord::TrackBitWidths::kRinvSize - 1,  // Width of pt
0085     kPtMagSize = 9,                                              // Width of pt magnitude (unsigned)
0086     kEtaSize = TTTrack_TrackWord::TrackBitWidths::kTanlSize,     // Width of eta
0087     kEtaMagSize = 3,                                             // Width of eta magnitude (signed)
0088   };
0089 
0090   typedef TTTrack<Ref_Phase2TrackerDigi_> TTTrackType;
0091   typedef std::vector<TTTrackType> TTTrackCollectionType;
0092   typedef edm::Handle<TTTrackCollectionType> TTTrackCollectionHandle;
0093   typedef edm::RefVector<TTTrackCollectionType> TTTrackRefCollectionType;
0094   typedef std::unique_ptr<TTTrackRefCollectionType> TTTrackRefCollectionUPtr;
0095 
0096   // ----------member functions ----------------------
0097   void printDebugInfo(const edm::Handle<TTTrackRefCollectionType>& l1SelectedTracksHandle,
0098                       const edm::Handle<TTTrackRefCollectionType>& l1SelectedTracksEmulationHandle,
0099                       const TTTrackRefCollectionUPtr& vTTTrackAssociatedOutput,
0100                       const TTTrackRefCollectionUPtr& vTTTrackAssociatedEmulationOutput) const;
0101   void printTrackInfo(edm::LogInfo& log, const TTTrackType& track, bool printEmulation = false) const;
0102   void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
0103 
0104   // ----------selectors -----------------------------
0105   // Based on recommendations from https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideGenericSelectors
0106   struct TTTrackDeltaZMaxSelector {
0107     TTTrackDeltaZMaxSelector(const std::vector<double>& deltaZMaxEtaBounds, const std::vector<double>& deltaZMax)
0108         : deltaZMaxEtaBounds_(deltaZMaxEtaBounds), deltaZMax_(deltaZMax) {}
0109     TTTrackDeltaZMaxSelector(const edm::ParameterSet& cfg)
0110         : deltaZMaxEtaBounds_(cfg.template getParameter<double>("deltaZMaxEtaBounds")),
0111           deltaZMax_(cfg.template getParameter<double>("deltaZMax")) {}
0112     bool operator()(const TTTrackType& t, const l1t::Vertex& v) const {
0113       size_t etaIndex =
0114           std::upper_bound(deltaZMaxEtaBounds_.begin(), deltaZMaxEtaBounds_.end(), std::abs(t.momentum().eta())) -
0115           deltaZMaxEtaBounds_.begin() - 1;
0116       if (etaIndex > deltaZMax_.size() - 1)
0117         etaIndex = deltaZMax_.size() - 1;
0118       return std::abs(v.z0() - t.z0()) <= deltaZMax_[etaIndex];
0119     }
0120 
0121   private:
0122     std::vector<double> deltaZMaxEtaBounds_;
0123     std::vector<double> deltaZMax_;
0124   };
0125   struct TTTrackWordDeltaZMaxSelector {
0126     TTTrackWordDeltaZMaxSelector(const std::vector<double>& deltaZMaxEtaBounds, const std::vector<double>& deltaZMax)
0127         : deltaZMaxEtaBounds_(deltaZMaxEtaBounds), deltaZMax_(deltaZMax) {}
0128     TTTrackWordDeltaZMaxSelector(const edm::ParameterSet& cfg)
0129         : deltaZMaxEtaBounds_(cfg.template getParameter<double>("deltaZMaxEtaBounds")),
0130           deltaZMax_(cfg.template getParameter<double>("deltaZMax")) {}
0131     bool operator()(const TTTrackType& t, const l1t::VertexWord& v) const {
0132       TTTrack_TrackWord::tanl_t etaEmulationBits = t.getTanlWord();
0133       ap_fixed<TrackBitWidths::kEtaSize, TrackBitWidths::kEtaMagSize> etaEmulation;
0134       etaEmulation.V = etaEmulationBits.range();
0135       size_t etaIndex =
0136           std::upper_bound(deltaZMaxEtaBounds_.begin(), deltaZMaxEtaBounds_.end(), std::abs(etaEmulation.to_double())) -
0137           deltaZMaxEtaBounds_.begin() - 1;
0138       if (etaIndex > deltaZMax_.size() - 1)
0139         etaIndex = deltaZMax_.size() - 1;
0140       l1t::VertexWord::vtxz0_t fixedTkZ0 = t.undigitizeSignedValue(
0141           t.getZ0Bits(), TTTrack_TrackWord::TrackBitWidths::kZ0Size, TTTrack_TrackWord::stepZ0, 0.0);
0142 
0143       ap_uint<TrackBitWidths::kPtSize> ptEmulationBits = t.getTrackWord()(
0144           TTTrack_TrackWord::TrackBitLocations::kRinvMSB - 1, TTTrack_TrackWord::TrackBitLocations::kRinvLSB);
0145       ap_ufixed<TrackBitWidths::kPtSize, TrackBitWidths::kPtMagSize> ptEmulation;
0146       ptEmulation.V = ptEmulationBits.range();
0147       return std::abs(v.z0() - fixedTkZ0.to_double()) <= deltaZMax_[etaIndex];
0148     }
0149 
0150   private:
0151     std::vector<double> deltaZMaxEtaBounds_;
0152     std::vector<double> deltaZMax_;
0153   };
0154 
0155   struct NNTrackWordSelector {
0156     NNTrackWordSelector(tensorflow::Session* AssociationSesh,
0157                         const double AssociationThreshold,
0158                         const std::vector<double>& AssociationNetworkZ0binning,
0159                         const std::vector<double>& AssociationNetworkEtaBounds,
0160                         const std::vector<double>& AssociationNetworkZ0ResBins)
0161         : AssociationSesh_(AssociationSesh),
0162           AssociationThreshold_(AssociationThreshold),
0163           z0_binning_(AssociationNetworkZ0binning),
0164           eta_bins_(AssociationNetworkEtaBounds),
0165           res_bins_(AssociationNetworkZ0ResBins) {}
0166 
0167     bool operator()(const TTTrackType& t, const l1t::VertexWord& v) const {
0168       tensorflow::Tensor inputAssoc(tensorflow::DT_FLOAT, {1, 4});
0169       std::vector<tensorflow::Tensor> outputAssoc;
0170 
0171       TTTrack_TrackWord::tanl_t etaEmulationBits = t.getTanlWord();
0172       ap_fixed<16, 3> etaEmulation;
0173       etaEmulation.V = (etaEmulationBits.range());
0174 
0175       auto lower = std::lower_bound(eta_bins_.begin(), eta_bins_.end(), etaEmulation.to_double());
0176 
0177       int resbin = std::distance(eta_bins_.begin(), lower);
0178       float binWidth = z0_binning_[2];
0179       // Calculate integer dZ from track z0 and vertex z0 (use floating point version and convert internally allowing use of both emulator and simulator vertex and track)
0180       float dZ =
0181           abs(floor(((t.getZ0() + z0_binning_[1]) / (binWidth))) - floor(((v.z0() + z0_binning_[1]) / (binWidth))));
0182 
0183       // The following constants <14, 9>, <22, 9> are defined by the quantisation of the Neural Network
0184       ap_uint<14> ptEmulationBits = t.getTrackWord()(TTTrack_TrackWord::TrackBitLocations::kRinvMSB - 1,
0185                                                      TTTrack_TrackWord::TrackBitLocations::kRinvLSB);
0186       ap_ufixed<14, 9> ptEmulation;
0187       ptEmulation.V = (ptEmulationBits.range());
0188 
0189       ap_ufixed<22, 9> ptEmulation_rescale;
0190       ptEmulation_rescale = ptEmulation.to_double();
0191 
0192       ap_ufixed<22, 9> resBinEmulation_rescale;
0193       resBinEmulation_rescale = res_bins_[resbin];
0194 
0195       ap_ufixed<22, 9> MVAEmulation_rescale;
0196       MVAEmulation_rescale = t.getMVAQualityBits();
0197 
0198       ap_ufixed<22, 9> dZEmulation_rescale;
0199       dZEmulation_rescale = dZ;
0200 
0201       inputAssoc.tensor<float, 2>()(0, 0) = ptEmulation_rescale.to_double();
0202       inputAssoc.tensor<float, 2>()(0, 1) = MVAEmulation_rescale.to_double();
0203       inputAssoc.tensor<float, 2>()(0, 2) = resBinEmulation_rescale.to_double() / 16.0;
0204       inputAssoc.tensor<float, 2>()(0, 3) = dZEmulation_rescale.to_double();
0205 
0206       // Run Association Network:
0207       tensorflow::run(AssociationSesh_, {{"assoc:0", inputAssoc}}, {"Identity:0"}, &outputAssoc);
0208 
0209       double NNOutput = (double)outputAssoc[0].tensor<float, 2>()(0, 0);
0210 
0211       double NNOutput_exp = 1.0 / (1.0 + exp(-1.0 * (NNOutput)));
0212 
0213       return NNOutput_exp >= AssociationThreshold_;
0214     }
0215 
0216   private:
0217     tensorflow::Session* AssociationSesh_;
0218     double AssociationThreshold_;
0219     std::vector<double> z0_binning_;
0220     std::vector<double> eta_bins_;
0221     std::vector<double> res_bins_;
0222   };
0223 
0224   struct TTTrackWordLinkLimitSelector {
0225     TTTrackWordLinkLimitSelector(const unsigned int fwNTrackSetsTVA) : fwNTrackSetsTVA_(fwNTrackSetsTVA) {
0226       //create a counter for all 18 GTT input links, 2 per phiSector of the TrackFindingProcessors
0227       for (int idx = 0; idx < 18; idx++) {
0228         processedTracksPerLink_.push_back(0);
0229         truncatedTracksPerLink_.push_back(0);
0230       }
0231     }
0232     TTTrackWordLinkLimitSelector(const edm::ParameterSet& cfg)
0233         : fwNTrackSetsTVA_(cfg.template getParameter<unsigned int>("fwNTrackSetsTVA")) {
0234       for (int idx = 0; idx < 18; idx++) {
0235         processedTracksPerLink_.push_back(0);
0236       }
0237     }
0238     bool operator()(const TTTrackType& t) {
0239       unsigned int gttLinkID = l1t::demo::codecs::gttLinkID(t);
0240       //increment the counter of processed tracks
0241       processedTracksPerLink_.at(gttLinkID)++;
0242       //fwNTrackSetsTVA_ tracks may be processed in firmware, no more (<= used intentionally to match the off-by-one indexing versus LibHLS)
0243       if ((processedTracksPerLink_[gttLinkID] > fwNTrackSetsTVA_) && (t.getValidWord()))
0244         truncatedTracksPerLink_[gttLinkID]++;
0245       return processedTracksPerLink_[gttLinkID] <= fwNTrackSetsTVA_;
0246     }
0247     void log() {
0248       edm::LogInfo log("L1TrackVertexAssociationProducer");
0249       log << "Processed track link counters:\t[";
0250       for (int idx = 0; idx < 18; idx++) {
0251         if (idx > 0)
0252           log << ", ";
0253         log << processedTracksPerLink_.at(idx);
0254       }
0255       log << "]\n";
0256       log << "Truncated track link counters:\t[";
0257       for (int idx = 0; idx < 18; idx++) {
0258         if (idx > 0)
0259           log << ", ";
0260         log << truncatedTracksPerLink_.at(idx);
0261       }
0262       log << "]\n";
0263     }
0264 
0265   private:
0266     unsigned int fwNTrackSetsTVA_;
0267     std::vector<unsigned int> processedTracksPerLink_;
0268     std::vector<unsigned int> truncatedTracksPerLink_;
0269   };
0270 
0271   // ----------member data ---------------------------
0272   const bool processSimulatedTracks_, processEmulatedTracks_;
0273   const edm::EDGetTokenT<TTTrackCollectionType> l1TracksToken_;
0274   const edm::EDGetTokenT<l1t::VertexCollection> l1VerticesToken_;
0275   const edm::EDGetTokenT<TTTrackRefCollectionType> l1SelectedTracksToken_;
0276   const edm::EDGetTokenT<l1t::VertexWordCollection> l1VerticesEmulationToken_;
0277   const edm::EDGetTokenT<TTTrackRefCollectionType> l1SelectedTracksEmulationToken_;
0278   const std::string outputCollectionName_;
0279   const edm::ParameterSet cutSet_;
0280   std::vector<double> deltaZMaxEtaBounds_, deltaZMax_;
0281   const double useDisplacedTracksDeltaZOverride_;
0282   // corresponds to N_TRACK_SETS_TVA in LibHLS https://gitlab.cern.ch/GTT/LibHLS/-/blob/master/DataFormats/Track/interface/TrackConstants.h
0283   const unsigned int fwNTrackSetsTVA_;
0284 
0285   //NNVtx:
0286   edm::FileInPath associationGraphPath_;
0287   const double associationThreshold_;
0288   bool useAssociationNetwork_;
0289   tensorflow::GraphDef* associationGraph_;
0290   tensorflow::Session* associationSesh_;
0291   std::vector<double> associationNetworkZ0binning_, associationNetworkEtaBounds_, associationNetworkZ0ResBins_;
0292 
0293   int debug_;
0294 };
0295 
0296 //
0297 // constructors and destructor
0298 //
0299 L1TrackVertexAssociationProducer::L1TrackVertexAssociationProducer(const edm::ParameterSet& iConfig)
0300     : processSimulatedTracks_(iConfig.getParameter<bool>("processSimulatedTracks")),
0301       processEmulatedTracks_(iConfig.getParameter<bool>("processEmulatedTracks")),
0302       l1TracksToken_(consumes<TTTrackCollectionType>(iConfig.getParameter<edm::InputTag>("l1TracksInputTag"))),
0303       l1VerticesToken_(processSimulatedTracks_
0304                            ? consumes<l1t::VertexCollection>(iConfig.getParameter<edm::InputTag>("l1VerticesInputTag"))
0305                            : edm::EDGetTokenT<l1t::VertexCollection>()),
0306       l1SelectedTracksToken_(
0307           processSimulatedTracks_
0308               ? consumes<TTTrackRefCollectionType>(iConfig.getParameter<edm::InputTag>("l1SelectedTracksInputTag"))
0309               : edm::EDGetTokenT<TTTrackRefCollectionType>()),
0310       l1VerticesEmulationToken_(
0311           processEmulatedTracks_
0312               ? consumes<l1t::VertexWordCollection>(iConfig.getParameter<edm::InputTag>("l1VerticesEmulationInputTag"))
0313               : edm::EDGetTokenT<l1t::VertexWordCollection>()),
0314       l1SelectedTracksEmulationToken_(processEmulatedTracks_
0315                                           ? consumes<TTTrackRefCollectionType>(iConfig.getParameter<edm::InputTag>(
0316                                                 "l1SelectedTracksEmulationInputTag"))
0317                                           : edm::EDGetTokenT<TTTrackRefCollectionType>()),
0318       outputCollectionName_(iConfig.getParameter<std::string>("outputCollectionName")),
0319       cutSet_(iConfig.getParameter<edm::ParameterSet>("cutSet")),
0320 
0321       deltaZMaxEtaBounds_(cutSet_.getParameter<std::vector<double>>("deltaZMaxEtaBounds")),
0322       deltaZMax_(cutSet_.getParameter<std::vector<double>>("deltaZMax")),
0323       useDisplacedTracksDeltaZOverride_(iConfig.getParameter<double>("useDisplacedTracksDeltaZOverride")),
0324       fwNTrackSetsTVA_(iConfig.getParameter<unsigned int>("fwNTrackSetsTVA")),
0325       associationThreshold_(iConfig.getParameter<double>("associationThreshold")),
0326       useAssociationNetwork_(iConfig.getParameter<bool>("useAssociationNetwork")),
0327       associationNetworkZ0binning_(iConfig.getParameter<std::vector<double>>("associationNetworkZ0binning")),
0328       associationNetworkEtaBounds_(iConfig.getParameter<std::vector<double>>("associationNetworkEtaBounds")),
0329       associationNetworkZ0ResBins_(iConfig.getParameter<std::vector<double>>("associationNetworkZ0ResBins")),
0330       debug_(iConfig.getParameter<int>("debug")) {
0331   if (useAssociationNetwork_) {
0332     associationGraphPath_ = iConfig.getParameter<edm::FileInPath>("associationGraph");
0333     associationGraph_ = tensorflow::loadGraphDef(associationGraphPath_.fullPath());
0334     associationSesh_ = tensorflow::createSession(associationGraph_);
0335   }
0336   // Confirm the the configuration makes sense
0337   if (!processSimulatedTracks_ && !processEmulatedTracks_) {
0338     throw cms::Exception("You must process at least one of the track collections (simulated or emulated).");
0339   }
0340 
0341   if (deltaZMax_.size() != deltaZMaxEtaBounds_.size() - 1) {
0342     throw cms::Exception("The number of deltaZ cuts does not match the number of eta bins!");
0343   }
0344 
0345   if (useDisplacedTracksDeltaZOverride_ >= 0) {
0346     deltaZMax_ = std::vector<double>(deltaZMax_.size(), useDisplacedTracksDeltaZOverride_);
0347   }
0348 
0349   // Get additional input tags and define the EDM output based on the previous configuration parameters
0350   if (processSimulatedTracks_)
0351     produces<TTTrackRefCollectionType>(outputCollectionName_);
0352   if (processEmulatedTracks_)
0353     produces<TTTrackRefCollectionType>(outputCollectionName_ + "Emulation");
0354 }
0355 
0356 L1TrackVertexAssociationProducer::~L1TrackVertexAssociationProducer() {}
0357 
0358 //
0359 // member functions
0360 //
0361 
0362 void L1TrackVertexAssociationProducer::printDebugInfo(
0363     const edm::Handle<TTTrackRefCollectionType>& l1SelectedTracksHandle,
0364     const edm::Handle<TTTrackRefCollectionType>& l1SelectedTracksEmulationHandle,
0365     const TTTrackRefCollectionUPtr& vTTTrackAssociatedOutput,
0366     const TTTrackRefCollectionUPtr& vTTTrackAssociatedEmulationOutput) const {
0367   edm::LogInfo log("L1TrackVertexAssociationProducer");
0368   if (processSimulatedTracks_) {
0369     log << "The original selected track collection (pt, eta, phi, nstub, bendchi2, chi2rz, chi2rphi, z0) values are "
0370            "... \n";
0371     for (const auto& track : *l1SelectedTracksHandle) {
0372       printTrackInfo(log, *track, debug_ >= 4);
0373     }
0374     log << "\t---\n\tNumber of tracks in this selection = " << l1SelectedTracksHandle->size() << "\n\n";
0375   }
0376   if (processEmulatedTracks_) {
0377     log << "The original selected emulated track collection (pt, eta, phi, nstub, bendchi2, chi2rz, chi2rphi, z0) "
0378            "values are ... \n";
0379     for (const auto& track : *l1SelectedTracksEmulationHandle) {
0380       printTrackInfo(log, *track, debug_ >= 4);
0381     }
0382     log << "\t---\n\tNumber of tracks in this selection = " << l1SelectedTracksEmulationHandle->size() << "\n\n";
0383   }
0384   if (processSimulatedTracks_ && processEmulatedTracks_) {
0385     TTTrackRefCollectionType inSimButNotEmu;
0386     TTTrackRefCollectionType inEmuButNotSim;
0387     std::set_difference(l1SelectedTracksHandle->begin(),
0388                         l1SelectedTracksHandle->end(),
0389                         l1SelectedTracksEmulationHandle->begin(),
0390                         l1SelectedTracksEmulationHandle->end(),
0391                         std::back_inserter(inSimButNotEmu));
0392     std::set_difference(l1SelectedTracksEmulationHandle->begin(),
0393                         l1SelectedTracksEmulationHandle->end(),
0394                         l1SelectedTracksHandle->begin(),
0395                         l1SelectedTracksHandle->end(),
0396                         std::back_inserter(inEmuButNotSim));
0397     log << "The set of tracks selected via cuts on the simulated values which are not in the set of tracks selected "
0398            "by cutting on the emulated values ... \n";
0399     for (const auto& track : inSimButNotEmu) {
0400       printTrackInfo(log, *track, debug_ >= 3);
0401     }
0402     log << "\t---\n\tNumber of tracks in this selection = " << inSimButNotEmu.size() << "\n\n"
0403         << "The set of tracks selected via cuts on the emulated values which are not in the set of tracks selected "
0404            "by cutting on the simulated values ... \n";
0405     for (const auto& track : inEmuButNotSim) {
0406       printTrackInfo(log, *track, debug_ >= 3);
0407     }
0408     log << "\t---\n\tNumber of tracks in this selection = " << inEmuButNotSim.size() << "\n\n";
0409   }
0410   if (processSimulatedTracks_) {
0411     log << "The selected and leading vertex associated track collection (pt, eta, phi, nstub, bendchi2, chi2rz, "
0412            "chi2rphi, z0) values are ... \n";
0413     for (const auto& track : *vTTTrackAssociatedOutput) {
0414       printTrackInfo(log, *track, debug_ >= 4);
0415     }
0416     log << "\t---\n\tNumber of tracks in this selection = " << vTTTrackAssociatedOutput->size() << "\n\n";
0417   }
0418   if (processEmulatedTracks_) {
0419     log << "The emulation selected and leading vertex associated track collection (pt, eta, phi, nstub, bendchi2, "
0420            "chi2rz, chi2rphi, z0) values are "
0421            "... \n";
0422     for (const auto& track : *vTTTrackAssociatedEmulationOutput) {
0423       printTrackInfo(log, *track, debug_ >= 4);
0424     }
0425     log << "\t---\n\tNumber of tracks in this selection = " << vTTTrackAssociatedEmulationOutput->size() << "\n\n";
0426   }
0427   if (processSimulatedTracks_ && processEmulatedTracks_) {
0428     TTTrackRefCollectionType inSimButNotEmu;
0429     TTTrackRefCollectionType inEmuButNotSim;
0430     std::set_difference(vTTTrackAssociatedOutput->begin(),
0431                         vTTTrackAssociatedOutput->end(),
0432                         vTTTrackAssociatedEmulationOutput->begin(),
0433                         vTTTrackAssociatedEmulationOutput->end(),
0434                         std::back_inserter(inSimButNotEmu));
0435     std::set_difference(vTTTrackAssociatedEmulationOutput->begin(),
0436                         vTTTrackAssociatedEmulationOutput->end(),
0437                         vTTTrackAssociatedOutput->begin(),
0438                         vTTTrackAssociatedOutput->end(),
0439                         std::back_inserter(inEmuButNotSim));
0440     log << "The set of vertex associated tracks selected via cuts on the simulated values which are not in the set of "
0441            "tracks selected "
0442            "by cutting on the emulated values ... \n";
0443     for (const auto& track : inSimButNotEmu) {
0444       printTrackInfo(log, *track, debug_ >= 3);
0445     }
0446     log << "\t---\n\tNumber of tracks in this selection = " << inSimButNotEmu.size() << "\n\n"
0447         << "The set of vertex associated tracks selected via cuts on the emulated values which are not in the set of "
0448            "tracks selected "
0449            "by cutting on the simulated values ... \n";
0450     for (const auto& track : inEmuButNotSim) {
0451       printTrackInfo(log, *track, debug_ >= 3);
0452     }
0453     log << "\t---\n\tNumber of tracks in this selection = " << inEmuButNotSim.size() << "\n\n";
0454   }
0455 }
0456 
0457 void L1TrackVertexAssociationProducer::printTrackInfo(edm::LogInfo& log,
0458                                                       const TTTrackType& track,
0459                                                       bool printEmulation) const {
0460   log << "\t(" << track.momentum().perp() << ", " << track.momentum().eta() << ", " << track.momentum().phi() << ", "
0461       << track.getStubRefs().size() << ", " << track.stubPtConsistency() << ", " << track.chi2ZRed() << ", "
0462       << track.chi2XYRed() << ", " << track.z0() << ")\n";
0463 
0464   if (printEmulation) {
0465     ap_uint<TrackBitWidths::kPtSize> ptEmulationBits = track.getTrackWord()(
0466         TTTrack_TrackWord::TrackBitLocations::kRinvMSB - 1, TTTrack_TrackWord::TrackBitLocations::kRinvLSB);
0467     ap_ufixed<TrackBitWidths::kPtSize, TrackBitWidths::kPtMagSize> ptEmulation;
0468     ptEmulation.V = ptEmulationBits.range();
0469     TTTrack_TrackWord::tanl_t etaEmulationBits = track.getTanlWord();
0470     ap_fixed<TrackBitWidths::kEtaSize, TrackBitWidths::kEtaMagSize> etaEmulation;
0471     etaEmulation.V = etaEmulationBits.range();
0472     double floatTkZ0 = track.undigitizeSignedValue(
0473         track.getZ0Bits(), TTTrack_TrackWord::TrackBitWidths::kZ0Size, TTTrack_TrackWord::stepZ0, 0.0);
0474     double floatTkPhi = track.undigitizeSignedValue(
0475         track.getPhiBits(), TTTrack_TrackWord::TrackBitWidths::kPhiSize, TTTrack_TrackWord::stepPhi0, 0.0);
0476     log << "\t\t(" << ptEmulation.to_double() << ", " << etaEmulation.to_double() << ", " << floatTkPhi << ", "
0477         << track.getNStubs() << ", " << track.getBendChi2() << ", " << track.getChi2RZ() << ", " << track.getChi2RPhi()
0478         << ", " << floatTkZ0 << ")\n";
0479   }
0480 }
0481 
0482 // ------------ method called to produce the data  ------------
0483 void L1TrackVertexAssociationProducer::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
0484   auto vTTTrackAssociatedOutput = std::make_unique<TTTrackRefCollectionType>();
0485   auto vTTTrackAssociatedEmulationOutput = std::make_unique<TTTrackRefCollectionType>();
0486 
0487   TTTrackCollectionHandle l1TracksHandle;
0488   edm::Handle<TTTrackRefCollectionType> l1SelectedTracksHandle;
0489   edm::Handle<TTTrackRefCollectionType> l1SelectedTracksEmulationHandle;
0490   edm::Handle<l1t::VertexCollection> l1VerticesHandle;
0491   edm::Handle<l1t::VertexWordCollection> l1VerticesEmulationHandle;
0492 
0493   l1t::Vertex leadingVertex;
0494   l1t::VertexWord leadingEmulationVertex;
0495 
0496   TTTrackWordLinkLimitSelector linkLimitSel(fwNTrackSetsTVA_);     //stateful functor for simulated tracks
0497   TTTrackWordLinkLimitSelector linkLimitSelEmu(fwNTrackSetsTVA_);  //stateful functor for emulated tracks
0498 
0499   TTTrackDeltaZMaxSelector deltaZSel(deltaZMaxEtaBounds_, deltaZMax_);
0500   TTTrackWordDeltaZMaxSelector deltaZSelEmu(deltaZMaxEtaBounds_, deltaZMax_);
0501 
0502   NNTrackWordSelector TTTrackNetworkSelector(associationSesh_,
0503                                              associationThreshold_,
0504                                              associationNetworkZ0binning_,
0505                                              associationNetworkEtaBounds_,
0506                                              associationNetworkZ0ResBins_);
0507 
0508   iEvent.getByToken(l1TracksToken_, l1TracksHandle);
0509   size_t nOutputApproximate = l1TracksHandle->size();
0510 
0511   if (processSimulatedTracks_) {
0512     iEvent.getByToken(l1SelectedTracksToken_, l1SelectedTracksHandle);
0513     iEvent.getByToken(l1VerticesToken_, l1VerticesHandle);
0514     leadingVertex = l1VerticesHandle->at(0);
0515     if (debug_ >= 2) {
0516       edm::LogInfo("L1TrackVertexAssociationProducer") << "leading vertex z0 = " << leadingVertex.z0();
0517     }
0518     vTTTrackAssociatedOutput->reserve(nOutputApproximate);
0519   }
0520   if (processEmulatedTracks_) {
0521     iEvent.getByToken(l1SelectedTracksEmulationToken_, l1SelectedTracksEmulationHandle);
0522     iEvent.getByToken(l1VerticesEmulationToken_, l1VerticesEmulationHandle);
0523     leadingEmulationVertex = l1VerticesEmulationHandle->at(0);
0524     if (debug_ >= 2) {
0525       edm::LogInfo("L1TrackVertexAssociationProducer")
0526           << "leading emulation vertex z0 = " << leadingEmulationVertex.z0();
0527     }
0528     vTTTrackAssociatedEmulationOutput->reserve(nOutputApproximate);
0529   }
0530   for (size_t i = 0; i < nOutputApproximate; i++) {
0531     const auto& track = l1TracksHandle->at(i);
0532     if (processSimulatedTracks_) {
0533       // Limit the number of processed tracks according to the firmware capability: must be run on non-selected tracks (i.e. GTTConverted tracks)
0534       bool passLinkLimit = linkLimitSel(track);
0535       // Only match Selected tracks, by testing that the track is in the SelectedTracks collection
0536       auto itr = std::find_if(l1SelectedTracksHandle->begin(), l1SelectedTracksHandle->end(), [track](const auto& ref) {
0537         return (*ref).getTrackWord() == track.getTrackWord();
0538       });
0539       bool passSelection = (itr != l1SelectedTracksHandle->end());
0540       // Associate tracks based on the simulation delta Z
0541       if (passLinkLimit && passSelection && deltaZSel(track, leadingVertex)) {
0542         vTTTrackAssociatedOutput->push_back(TTTrackRef(l1TracksHandle, i));
0543       }
0544     }  //end if (processSimulatedTracks_)
0545     if (processEmulatedTracks_) {
0546       // Limit the number of processed tracks according to the firmware capability: must be run on non-selected tracks (i.e. GTTConverted tracks)
0547       bool passLinkLimitEmu = linkLimitSelEmu(track);
0548       // Only match Selected tracks, by testing that the track is in the SelectedTracks collection
0549       auto itrEmu = std::find_if(l1SelectedTracksEmulationHandle->begin(),
0550                                  l1SelectedTracksEmulationHandle->end(),
0551                                  [track](const auto& ref) { return (*ref).getTrackWord() == track.getTrackWord(); });
0552       bool passSelectionEmu = (itrEmu != l1SelectedTracksEmulationHandle->end());
0553       // Associated tracks based on the bitwise accurate TTTrack_TrackWord
0554       if (useAssociationNetwork_) {
0555         if (passLinkLimitEmu && passSelectionEmu && TTTrackNetworkSelector(track, l1VerticesEmulationHandle->at(0))) {
0556           vTTTrackAssociatedEmulationOutput->push_back(TTTrackRef(l1TracksHandle, i));
0557         }
0558       } else {
0559         if (passLinkLimitEmu && passSelectionEmu && deltaZSelEmu(track, l1VerticesEmulationHandle->at(0))) {
0560           vTTTrackAssociatedEmulationOutput->push_back(TTTrackRef(l1TracksHandle, i));
0561         }  //end block for satisfying LinkLimitEmu and SelectionEmu criteria
0562       }  //end if use track association NN
0563     }  //end if (processEmulatedTracks_)
0564   }  //end loop over input converted tracks
0565 
0566   if (processSimulatedTracks_ && processEmulatedTracks_ && debug_ >= 2) {
0567     printDebugInfo(l1SelectedTracksHandle,
0568                    l1SelectedTracksEmulationHandle,
0569                    vTTTrackAssociatedOutput,
0570                    vTTTrackAssociatedEmulationOutput);
0571   }
0572 
0573   if (processSimulatedTracks_) {
0574     iEvent.put(std::move(vTTTrackAssociatedOutput), outputCollectionName_);
0575   }
0576 
0577   if (processEmulatedTracks_) {
0578     iEvent.put(std::move(vTTTrackAssociatedEmulationOutput), outputCollectionName_ + "Emulation");
0579     if (debug_ >= 2)
0580       linkLimitSelEmu.log();
0581   }
0582 }
0583 
0584 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0585 void L1TrackVertexAssociationProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0586   edm::ParameterSetDescription desc;
0587   desc.add<edm::InputTag>("l1TracksInputTag", edm::InputTag("l1tGTTInputProducer", "Level1TTTracksConverted"));
0588   desc.add<edm::InputTag>("l1SelectedTracksInputTag",
0589                           edm::InputTag("l1tTrackSelectionProducer", "Level1TTTracksSelected"));
0590   desc.add<edm::InputTag>("l1SelectedTracksEmulationInputTag",
0591                           edm::InputTag("l1tTrackSelectionProducer", "Level1TTTracksSelectedEmulation"));
0592   desc.add<edm::InputTag>("l1VerticesInputTag", edm::InputTag("l1tVertexFinder", "L1Vertices"));
0593   desc.add<edm::InputTag>("l1VerticesEmulationInputTag",
0594                           edm::InputTag("l1tVertexFinderEmulator", "L1VerticesEmulation"));
0595   desc.add<std::string>("outputCollectionName", "Level1TTTracksSelectedAssociated");
0596   {
0597     edm::ParameterSetDescription descCutSet;
0598     descCutSet.add<std::vector<double>>("deltaZMaxEtaBounds", {0.0, 0.7, 1.0, 1.2, 1.6, 2.0, 2.4})
0599         ->setComment("these values define the bin boundaries in |eta|");
0600     descCutSet.add<std::vector<double>>("deltaZMax", {0.37, 0.50, 0.60, 0.75, 1.00, 1.60})
0601         ->setComment(
0602             "delta z must be less than these values, there will be one less value here than in deltaZMaxEtaBounds, "
0603             "[cm]");
0604     desc.add<edm::ParameterSetDescription>("cutSet", descCutSet);
0605   }
0606   desc.add<double>("useDisplacedTracksDeltaZOverride", -1.0)
0607       ->setComment("override the deltaZ cut value for displaced tracks");
0608   desc.add<bool>("processSimulatedTracks", true)
0609       ->setComment("return selected tracks after cutting on the floating point values");
0610   desc.add<bool>("processEmulatedTracks", true)
0611       ->setComment("return selected tracks after cutting on the bitwise emulated values");
0612   desc.add<unsigned int>("fwNTrackSetsTVA", 94)->setComment("firmware limit on processed tracks per GTT input link");
0613   desc.add<bool>("useAssociationNetwork", false)->setComment("Enable Association Network");
0614   desc.add<double>("associationThreshold", 0)->setComment("Association Network threshold for PV tracks");
0615   desc.addOptional<edm::FileInPath>("associationGraph")->setComment("Location of Association Network model file");
0616   desc.add<std::vector<double>>("associationNetworkZ0binning", {})
0617       ->setComment("z0 binning used for setting the input feature digitisation");
0618   desc.add<std::vector<double>>("associationNetworkEtaBounds", {})
0619       ->setComment("Eta bounds used to set z0 resolution input feature");
0620   desc.add<std::vector<double>>("associationNetworkZ0ResBins", {})->setComment("z0 resolution input feature bins");
0621 
0622   desc.add<int>("debug", 0)->setComment("Verbosity levels: 0, 1, 2, 3");
0623   descriptions.addWithDefaultLabel(desc);
0624 }
0625 
0626 //define this as a plug-in
0627 DEFINE_FWK_MODULE(L1TrackVertexAssociationProducer);