Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-03 00:12:17

0001 #include "L1Trigger/TrackerTFP/interface/TrackFindingProcessor.h"
0002 #include "L1Trigger/TrackTrigger/interface/StubPtConsistency.h"
0003 
0004 #include <numeric>
0005 #include <algorithm>
0006 #include <iterator>
0007 #include <deque>
0008 #include <vector>
0009 
0010 namespace trackerTFP {
0011 
0012   TrackFindingProcessor::TrackFindingProcessor(const tt::Setup* setup,
0013                                                const DataFormats* dataFormats,
0014                                                const TrackQuality* trackQuality)
0015       : setup_(setup), dataFormats_(dataFormats), trackQuality_(trackQuality) {
0016     bfield_ = setup_->bField();
0017   }
0018 
0019   //
0020   TrackFindingProcessor::Track::Track(const tt::FrameTrack& frameTrack,
0021                                       const tt::Frame& frameTQ,
0022                                       const std::vector<TTStubRef>& ttStubRefs,
0023                                       const TrackQuality* tq)
0024       : ttTrackRef_(frameTrack.first), ttStubRefs_(ttStubRefs), valid_(true) {
0025     partials_.reserve(partial_in);
0026     const double rangeInvR = -2. * TTTrack_TrackWord::minRinv;
0027     const double rangePhi0 = -2. * TTTrack_TrackWord::minPhi0;
0028     const double rangeCot = -2. * TTTrack_TrackWord::minTanl;
0029     const double rangeZ0 = -2. * TTTrack_TrackWord::minZ0;
0030     const double rangeD0 = -2. * TTTrack_TrackWord::minD0;
0031     const double baseInvR = rangeInvR / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kRinvSize);
0032     const double basePhi0 = rangePhi0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kPhiSize);
0033     const double baseCot = rangeCot / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kTanlSize);
0034     const double baseZ0 = rangeZ0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kZ0Size);
0035     const double baseD0 = rangeD0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kD0Size);
0036     const int nLayers = TTTrack_TrackWord::TrackBitWidths::kHitPatternSize;
0037     const TTBV other_MVAs = TTBV(0, 2 * TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize);
0038     const TTBV chi2bend = TTBV(0, TTTrack_TrackWord::TrackBitWidths::kBendChi2Size);
0039     const TTBV valid = TTBV(1, TTTrack_TrackWord::TrackBitWidths::kValidSize);
0040     // convert bits into nice formats
0041     const DataFormats* df = tq->dataFormats();
0042     const tt::Setup* setup = df->setup();
0043     const TrackDR trackDR(frameTrack, df);
0044     inv2R_ = trackDR.inv2R();
0045     phiT_ = trackDR.phiT();
0046     cot_ = trackDR.cot();
0047     zT_ = trackDR.zT();
0048     const double d0 = std::max(std::min(ttTrackRef_->d0(), -TTTrack_TrackWord::minD0), TTTrack_TrackWord::minD0);
0049     TTBV ttBV = TTBV(frameTQ);
0050     tq->format(VariableTQ::chi2rz).extract(ttBV, chi2rz_);
0051     tq->format(VariableTQ::chi2rphi).extract(ttBV, chi2rphi_);
0052     mva_ = TTBV(ttBV, numBinsMVA_).val();
0053     ttBV >>= numBinsMVA_;
0054     hitPattern_ = ttBV;
0055     channel_ = cot_ < 0. ? 0 : 1;
0056     // convert nice formats into bits
0057     const double z0 = zT_ - cot_ * setup->chosenRofZ();
0058     const double phi0 = phiT_ - inv2R_ * setup->chosenRofPhi();
0059     double invR = -2. * inv2R_;
0060     if (invR < TTTrack_TrackWord::minRinv)
0061       invR = TTTrack_TrackWord::minRinv + df->format(Variable::inv2R, Process::dr).base();
0062     else if (invR > -TTTrack_TrackWord::minRinv)
0063       invR = -TTTrack_TrackWord::minRinv - df->format(Variable::inv2R, Process::dr).base();
0064     const double chi2rphi = chi2rphi_ / (hitPattern_.count() - 2);
0065     const double chi2rz = chi2rz_ / (hitPattern_.count() - 2);
0066     int chi2rphiBin(-1);
0067     for (double d : TTTrack_TrackWord::chi2RPhiBins)
0068       if (chi2rphi >= d)
0069         chi2rphiBin++;
0070       else
0071         break;
0072     int chi2rzBin(-1);
0073     for (double d : TTTrack_TrackWord::chi2RZBins)
0074       if (chi2rz >= d)
0075         chi2rzBin++;
0076       else
0077         break;
0078     if (std::abs(invR) > rangeInvR / 2.)
0079       valid_ = false;
0080     if (std::abs(phi0) > rangePhi0 / 2.)
0081       valid_ = false;
0082     if (std::abs(cot_) > rangeCot / 2.)
0083       valid_ = false;
0084     if (std::abs(z0) > rangeZ0 / 2.)
0085       valid_ = false;
0086     if (std::abs(d0) > rangeD0 / 2.)
0087       valid_ = false;
0088     if (!valid_)
0089       return;
0090     const TTBV MVA_quality(mva_, TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize);
0091     const TTBV hit_pattern(hitPattern_.resize(nLayers).val(), nLayers);
0092     const TTBV D0(d0, baseD0, TTTrack_TrackWord::TrackBitWidths::kD0Size, true);
0093     const TTBV Chi2rz(chi2rzBin, TTTrack_TrackWord::TrackBitWidths::kChi2RZSize);
0094     const TTBV Z0(z0, baseZ0, TTTrack_TrackWord::TrackBitWidths::kZ0Size, true);
0095     const TTBV tanL(cot_, baseCot, TTTrack_TrackWord::TrackBitWidths::kTanlSize, true);
0096     const TTBV Chi2rphi(chi2rphiBin, TTTrack_TrackWord::TrackBitWidths::kChi2RPhiSize);
0097     const TTBV Phi0(phi0, basePhi0, TTTrack_TrackWord::TrackBitWidths::kPhiSize, true);
0098     const TTBV InvR(invR, baseInvR, TTTrack_TrackWord::TrackBitWidths::kRinvSize, true);
0099     partials_.emplace_back((valid + InvR + Phi0 + Chi2rphi).str());
0100     partials_.emplace_back((tanL + Z0 + Chi2rz).str());
0101     partials_.emplace_back((D0 + chi2bend + hit_pattern + MVA_quality + other_MVAs).str());
0102   }
0103 
0104   // fill output products
0105   void TrackFindingProcessor::produce(const tt::StreamsTrack& inputs,
0106                                       const tt::StreamsStub& stubs,
0107                                       tt::TTTracks& ttTracks,
0108                                       tt::StreamsTrack& outputs) {
0109     // organize input tracks
0110     std::vector<std::deque<Track*>> streams(outputs.size());
0111     consume(inputs, stubs, streams);
0112     // emualte data format f/w
0113     produce(streams, outputs);
0114     // produce TTTracks
0115     produce(outputs, ttTracks);
0116   }
0117 
0118   //
0119   void TrackFindingProcessor::consume(const tt::StreamsTrack& inputs,
0120                                       const tt::StreamsStub& stubs,
0121                                       std::vector<std::deque<Track*>>& outputs) {
0122     // count input objects
0123     int nTracks(0);
0124     auto valid = [](int sum, const tt::FrameTrack& frame) { return sum + (frame.first.isNonnull() ? 1 : 0); };
0125     for (const tt::StreamTrack& tracks : inputs)
0126       nTracks += std::accumulate(tracks.begin(), tracks.end(), 0, valid);
0127     tracks_.reserve(nTracks);
0128     // convert input data
0129     for (int region = 0; region < setup_->numRegions(); region++) {
0130       const int offsetTQ = region * setup_->tqNumChannel();
0131       const int offsetTFP = region * setup_->tfpNumChannel();
0132       const int offsetStub = region * setup_->numLayers();
0133       const tt::StreamTrack& streamDR = inputs[offsetTQ];
0134       const tt::StreamTrack& streamTQ = inputs[offsetTQ + 1];
0135       for (int channel = 0; channel < setup_->tfpNumChannel(); channel++)
0136         outputs[offsetTFP + channel] = std::deque<Track*>(streamDR.size(), nullptr);
0137       for (int frame = 0; frame < static_cast<int>(streamDR.size()); frame++) {
0138         const tt::FrameTrack& frameTrack = streamDR[frame];
0139         const tt::Frame& frameTQ = streamTQ[frame].second;
0140         if (frameTrack.first.isNull())
0141           continue;
0142         std::vector<TTStubRef> ttStubRefs;
0143         ttStubRefs.reserve(setup_->numLayers());
0144         for (int layer = 0; layer < setup_->numLayers(); layer++) {
0145           const TTStubRef& ttStubRef = stubs[offsetStub + layer][frame].first;
0146           if (ttStubRef.isNonnull())
0147             ttStubRefs.push_back(ttStubRef);
0148         }
0149         tracks_.emplace_back(frameTrack, frameTQ, ttStubRefs, trackQuality_);
0150         Track& track = tracks_.back();
0151         outputs[offsetTFP + track.channel_][frame] = track.valid_ ? &track : nullptr;
0152       }
0153       // remove all gaps between end and last track
0154       for (int channel = 0; channel < setup_->tfpNumChannel(); channel++) {
0155         std::deque<Track*> input = outputs[offsetTFP + channel];
0156         for (auto it = input.end(); it != input.begin();)
0157           it = (*--it) ? input.begin() : input.erase(it);
0158       }
0159     }
0160   }
0161 
0162   // emualte data format f/w
0163   void TrackFindingProcessor::produce(std::vector<std::deque<Track*>>& inputs, tt::StreamsTrack& outputs) const {
0164     for (int channel = 0; channel < static_cast<int>(inputs.size()); channel++) {
0165       std::deque<Track*>& input = inputs[channel];
0166       std::deque<PartialFrameTrack> stack;
0167       std::deque<tt::FrameTrack> output;
0168       // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
0169       while (!input.empty() || !stack.empty()) {
0170         output.emplace_back(tt::FrameTrack());
0171         tt::FrameTrack& frame = output.back();
0172         Track* track = pop_front(input);
0173         if (track)
0174           for (const PartialFrame& pf : track->partials_)
0175             stack.emplace_back(track->ttTrackRef_, pf);
0176         TTBV ttBV;
0177         for (int i = 0; i < partial_out; i++) {
0178           if (stack.empty()) {
0179             ttBV += TTBV(0, partial_width);
0180             continue;
0181           }
0182           const PartialFrameTrack& pft = stack.front();
0183           frame.first = pft.first;
0184           ttBV += TTBV(pft.second.to_string());
0185           stack.pop_front();
0186         }
0187         frame.second = ttBV.bs();
0188       }
0189       // perorm truncation
0190       if (setup_->enableTruncation() && static_cast<int>(output.size()) > setup_->numFramesIOHigh())
0191         output.resize(setup_->numFramesIOHigh());
0192       outputs[channel] = tt::StreamTrack(output.begin(), output.end());
0193     }
0194   }
0195 
0196   // produce TTTracks
0197   void TrackFindingProcessor::produce(const tt::StreamsTrack& inputs, tt::TTTracks& outputs) const {
0198     // collect input TTTrackRefs
0199     std::vector<TTTrackRef> ttTrackRefs;
0200     ttTrackRefs.reserve(tracks_.size());
0201     const TTTrack<Ref_Phase2TrackerDigi_>* last = nullptr;
0202     for (const tt::StreamTrack& stream : inputs) {
0203       for (const tt::FrameTrack& frame : stream) {
0204         const TTTrackRef& ttTrackRef = frame.first;
0205         if (frame.first.isNull() || last == ttTrackRef.get())
0206           continue;
0207         last = ttTrackRef.get();
0208         ttTrackRefs.push_back(ttTrackRef);
0209       }
0210     }
0211     // convert input TTTrackRefs into output TTTracks
0212     const DataFormat& dfZT = dataFormats_->format(Variable::zT, Process::gp);
0213     outputs.reserve(ttTrackRefs.size());
0214     for (const TTTrackRef& ttTrackRef : ttTrackRefs) {
0215       auto match = [&ttTrackRef](const Track& track) { return track.ttTrackRef_ == ttTrackRef; };
0216       const auto it = std::find_if(tracks_.begin(), tracks_.end(), match);
0217       // TTTrack conversion
0218       const int region = ttTrackRef->phiSector();
0219       const double aRinv = -2. * it->inv2R_;
0220       const double aphi = tt::deltaPhi(it->phiT_ - it->inv2R_ * setup_->chosenRofPhi() + region * setup_->baseRegion());
0221       const double aTanLambda = it->cot_;
0222       const double az0 = it->zT_ - it->cot_ * setup_->chosenRofZ();
0223       const double ad0 = -ttTrackRef->d0();
0224       const double aChi2xyfit = it->chi2rphi_;
0225       const double aChi2zfit = it->chi2rz_;
0226       const double trkMVA1 = (TTTrack_TrackWord::tqMVABins[it->mva_]);
0227       static constexpr double trkMVA2 = 0.;
0228       static constexpr double trkMVA3 = 0.;
0229       const unsigned int aHitpattern = it->hitPattern_.val();
0230       const unsigned int nPar = ttTrackRef->nFitPars();
0231       outputs.emplace_back(aRinv,
0232                            aphi,
0233                            aTanLambda,
0234                            az0,
0235                            ad0,
0236                            aChi2xyfit,
0237                            aChi2zfit,
0238                            trkMVA1,
0239                            trkMVA2,
0240                            trkMVA3,
0241                            aHitpattern,
0242                            nPar,
0243                            bfield_);
0244       TTTrack<Ref_Phase2TrackerDigi_>& ttTrack = outputs.back();
0245       ttTrack.setPhiSector(region);
0246       ttTrack.setEtaSector(dfZT.toUnsigned(dfZT.integer(it->zT_)));
0247       ttTrack.setTrackSeedType(ttTrackRef->trackSeedType());
0248       ttTrack.setStubRefs(it->ttStubRefs_);
0249       ttTrack.setStubPtConsistency(StubPtConsistency::getConsistency(
0250           ttTrack, setup_->trackerGeometry(), setup_->trackerTopology(), bfield_, nPar));
0251     }
0252   }
0253 
0254   // produce StreamsTrack
0255   void TrackFindingProcessor::produce(const std::vector<TTTrackRef>& inputs, tt::StreamsTrack& outputs) const {
0256     int iTrk(-1);
0257     const TTTrack<Ref_Phase2TrackerDigi_>* last = nullptr;
0258     for (tt::StreamTrack& stream : outputs) {
0259       for (tt::FrameTrack& frame : stream) {
0260         const TTTrackRef& ttTrackRef = frame.first;
0261         if (ttTrackRef.isNull())
0262           continue;
0263         if (last != ttTrackRef.get())
0264           iTrk++;
0265         last = ttTrackRef.get();
0266         frame.first = inputs[iTrk];
0267       }
0268     }
0269   }
0270 
0271   // remove and return first element of deque, returns nullptr if empty
0272   template <class T>
0273   T* TrackFindingProcessor::pop_front(std::deque<T*>& ts) const {
0274     T* t = nullptr;
0275     if (!ts.empty()) {
0276       t = ts.front();
0277       ts.pop_front();
0278     }
0279     return t;
0280   }
0281 
0282 }  // namespace trackerTFP