Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 //--- Note that the word "link" appearing in the C++ or comments in this class actually corresponds
0002 //--- to a pair of links in the hardware.
0003 
0004 #include "L1Trigger/TrackFindingTMTT/interface/MuxHToutputs.h"
0005 #include "L1Trigger/TrackFindingTMTT/interface/Settings.h"
0006 #include "L1Trigger/TrackFindingTMTT/interface/PrintL1trk.h"
0007 
0008 #include "FWCore/Utilities/interface/Exception.h"
0009 
0010 #include <sstream>
0011 #include <mutex>
0012 
0013 using namespace std;
0014 
0015 namespace tmtt {
0016 
0017   //=== Initialize constants from configuration parameters.
0018 
0019   MuxHToutputs::MuxHToutputs(const Settings* settings)
0020       : settings_(settings),
0021         muxOutputsHT_(static_cast<MuxAlgoName>(settings_->muxOutputsHT())),
0022         numPhiNonants_(settings_->numPhiNonants()),
0023         numPhiSectors_(settings_->numPhiSectors()),
0024         numPhiSecPerNon_(numPhiSectors_ / numPhiNonants_),
0025         numEtaRegions_(settings_->numEtaRegions()),
0026         busySectorKill_(settings_->busySectorKill()),          // Kill excess tracks flowing out of HT?
0027         busySectorNumStubs_(settings_->busySectorNumStubs()),  // Max. num. of stubs that can be sent within TM period
0028         busySectorMbinRanges_(
0029             settings_->busySectorMbinRanges()),  // Individual m bin (=q/Pt) ranges to be output to opto-links.
0030         busySectorUseMbinRanges_(not busySectorMbinRanges_.empty())  // m bin ranges option disabled if vector empty.
0031   {
0032     // Implemented MUX algorithm relies on same number of sectors per nonant.
0033     if (numPhiSectors_ % numPhiNonants_ != 0)
0034       throw cms::Exception("BadConfig")
0035           << "MuxHToutputs: Number of phi sectors is not a multiple of number of nonants!";
0036 
0037     if (!busySectorUseMbinRanges_)
0038       throw cms::Exception("BadConfig") << "MuxHToutputs: The implemented MUX algorithm requires you to be using the "
0039                                            "busySectorMbinRanges cfg option!";
0040 
0041     // Check that the MUX algorithm implemented in linkID() is not obviously wrong.
0042     this->sanityCheck();
0043 
0044     std::stringstream text;
0045     text << "=== The R-PHI HT output is multiplexed onto " << this->numLinksPerNonant()
0046          << " pairs of opto-links per nonant.";
0047     static std::once_flag printOnce;
0048     std::call_once(printOnce, [](string t) { PrintL1trk() << t; }, text.str());
0049   }
0050 
0051   //=== Determine which tracks are transmitted on each HT output optical link, taking into account the multiplexing
0052   //=== of multiple (eta,phi) sectors onto single links and the truncation of the tracks caused by the requirement
0053   //=== to output all the tracks within the time-multiplexed period.
0054   //=== This function replaces the 2D track collection in the r-phi HT with the subset surviving the TM cut.
0055 
0056   void MuxHToutputs::exec(Array2D<unique_ptr<HTrphi>>& mHtRphis) const {
0057     // As this loops over sectors in order of increasing sector number, this MUX algorithm always transmits tracks
0058     // from the lowest sector numbers on each link first. So the highest sector numbers are more likely to be
0059     // truncated by the TM period. The algorithm assumes that two or more m-bin ranges from the same sector will never
0060     // be transmitted down the same link, as if this happens, it does not predict the order in which they will be
0061     // transmitted.
0062 
0063     for (unsigned int iPhiNon = 0; iPhiNon < numPhiNonants_; iPhiNon++) {
0064       vector<unsigned int> numStubsPerLink(this->numLinksPerNonant(), 0);
0065 
0066       for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
0067         unsigned int iPhiSec = iPhiNon * numPhiSecPerNon_ + iSecInNon;
0068 
0069         for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
0070           HTrphi* htRphi = mHtRphis(iPhiSec, iEtaReg).get();  // Get a mutable version of the r-phi HT.
0071 
0072           list<L1track2D> keptTracks;
0073           const list<L1track2D>& tracks = htRphi->trackCands2D();
0074 
0075           for (const L1track2D& trk : tracks) {
0076             L1track2D trkTmp = trk;
0077             unsigned int nStubs = trkTmp.numStubs();                // #stubs on this track.
0078             unsigned int mBinRange = htRphi->getMbinRange(trkTmp);  // Which m bin range is this track in?
0079             // Get the output optical link corresponding to this sector & m-bin range.
0080             unsigned int link = this->linkID(iSecInNon, iEtaReg, mBinRange);
0081             // Make a note of opto-link number inside track object.
0082             trkTmp.setOptoLinkID(link);
0083 
0084             numStubsPerLink[link] += nStubs;
0085             // Check if this track can be output within the time-multiplexed period.
0086             bool keep = ((not busySectorKill_) || (numStubsPerLink[link] <= busySectorNumStubs_));
0087             // FIX: with 2 GeV threshold, this causes significant truncation.
0088             // Consider using one output link for each phi sector in nonant
0089             if (keep)
0090               keptTracks.push_back(trkTmp);
0091           }
0092 
0093           // Replace the collection of 2D tracks in the r-phi HT with the subset of them surviving the TM cut.
0094           htRphi->replaceTrackCands2D(keptTracks);
0095         }
0096       }
0097     }
0098   }
0099 
0100   //=== Define the number of (eta,phi) sectors that each output opto-link takes tracks from. (Depends on MUX scheme).
0101 
0102   unsigned int MuxHToutputs::muxFactor() const {
0103     if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
0104       return numEtaRegions_ * numPhiSecPerNon_;
0105     } else {
0106       throw cms::Exception("BadConfig") << "MuxHToutputs: Unknown MuxOutputsHT configuration option!";
0107     }
0108   }
0109 
0110   //=== Define the MUX algorithm by which tracks from the specified m-bin range in the HT for a given (phi,eta)
0111   //=== sector within a phi nonant are multiplexed onto a single output optical link.
0112 
0113   unsigned int MuxHToutputs::linkID(unsigned int iSecInNon, unsigned int iEtaReg, unsigned int mBinRange) const {
0114     unsigned int link;
0115 
0116     if (muxOutputsHT_ == MuxAlgoName::mBinPerLink) {
0117       //--- This is the Sept. 2019 Mux for the transverse HT readout organised by m-bin. (Each m bin in entire nonant goes to a different link).
0118 
0119       link = 0;
0120       link += mBinRange;
0121 
0122     } else {
0123       throw cms::Exception("BadConfig") << "MuxHToutputs: Unknown MuxOutputsHT configuration option!";
0124     }
0125 
0126     if (link >= this->numLinksPerNonant())
0127       throw cms::Exception("LogicError") << "MuxHToutputs: Calculated link ID exceeded expected number of links! "
0128                                          << link << " " << this->numLinksPerNonant();
0129     return link;
0130   }
0131 
0132   //=== Do sanity check of the MUX algorithm implemented in linkID().
0133 
0134   void MuxHToutputs::sanityCheck() {
0135     if (numPhiSecPerNon_ * numEtaRegions_ % this->muxFactor() != 0)
0136       throw cms::Exception("LogicError")
0137           << "MuxHToutputs: Number of sectors per phi nonant is not a multiple of muxFactor().";
0138 
0139     vector<unsigned int> nObsElementsPerLink(this->numLinksPerNonant(), 0);
0140     for (unsigned int iSecInNon = 0; iSecInNon < numPhiSecPerNon_; iSecInNon++) {
0141       for (unsigned int iEtaReg = 0; iEtaReg < numEtaRegions_; iEtaReg++) {
0142         unsigned int iCorr = (settings_->miniHTstage()) ? 1 : 0;
0143         for (unsigned int mBinRange = 0; mBinRange < busySectorMbinRanges_.size() - iCorr; mBinRange++) {
0144           unsigned int link = this->linkID(iSecInNon, iEtaReg, mBinRange);
0145           nObsElementsPerLink[link] += 1;
0146         }
0147       }
0148     }
0149   }
0150 
0151 }  // namespace tmtt