Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "L1Trigger/TrackFindingTracklet/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 trklet {
0011 
0012   TrackFindingProcessor::TrackFindingProcessor(const tt::Setup* setup,
0013                                                const DataFormats* dataFormats,
0014                                                const trackerTFP::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 DataFormats* df,
0024                                       const trackerTFP::TrackQuality* tq)
0025       : ttTrackRef_(frameTrack.first), ttStubRefs_(ttStubRefs), valid_(true) {
0026     partials_.reserve(partial_in);
0027     const double rangeInvR = -2. * TTTrack_TrackWord::minRinv;
0028     const double rangePhi0 = -2. * TTTrack_TrackWord::minPhi0;
0029     const double rangeCot = -2. * TTTrack_TrackWord::minTanl;
0030     const double rangeZ0 = -2. * TTTrack_TrackWord::minZ0;
0031     const double rangeD0 = -2. * TTTrack_TrackWord::minD0;
0032     const double baseInvR = rangeInvR / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kRinvSize);
0033     const double basePhi0 = rangePhi0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kPhiSize);
0034     const double baseCot = rangeCot / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kTanlSize);
0035     const double baseZ0 = rangeZ0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kZ0Size);
0036     const double baseD0 = rangeD0 / std::pow(2., TTTrack_TrackWord::TrackBitWidths::kD0Size);
0037     const int nLayers = TTTrack_TrackWord::TrackBitWidths::kHitPatternSize;
0038     const TTBV other_MVAs = TTBV(0, 2 * TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize);
0039     const TTBV chi2bend = TTBV(0, TTTrack_TrackWord::TrackBitWidths::kBendChi2Size);
0040     const TTBV valid = TTBV(1, TTTrack_TrackWord::TrackBitWidths::kValidSize);
0041     // convert bits into nice formats
0042     const tt::Setup* setup = df->setup();
0043     const TrackKF track(frameTrack, df);
0044     inv2R_ = track.inv2R();
0045     phiT_ = track.phiT();
0046     cot_ = track.cot();
0047     zT_ = track.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(trackerTFP::VariableTQ::chi2rz).extract(ttBV, chi2rz_);
0051     tq->format(trackerTFP::VariableTQ::chi2rphi).extract(ttBV, chi2rphi_);
0052     mva_ = TTBV(ttBV, trackerTFP::widthMVA_).val();
0053     ttBV >>= trackerTFP::widthMVA_;
0054     hitPattern_ = TTBV(ttBV, setup->numLayers());
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::Streams& inputsAdd,
0107                                       const tt::StreamsStub& stubs,
0108                                       tt::TTTracks& ttTracks,
0109                                       tt::StreamsTrack& outputs) {
0110     // organize input tracks
0111     std::vector<std::deque<Track*>> streams(outputs.size());
0112     consume(inputs, inputsAdd, stubs, streams);
0113     // emualte data format f/w
0114     produce(streams, outputs);
0115     // produce TTTracks
0116     produce(outputs, ttTracks);
0117   }
0118 
0119   //
0120   void TrackFindingProcessor::consume(const tt::StreamsTrack& inputs,
0121                                       const tt::Streams& inputsAdd,
0122                                       const tt::StreamsStub& stubs,
0123                                       std::vector<std::deque<Track*>>& outputs) {
0124     // count input objects
0125     int nTracks(0);
0126     auto valid = [](int sum, const tt::FrameTrack& frame) { return sum + (frame.first.isNonnull() ? 1 : 0); };
0127     for (const tt::StreamTrack& tracks : inputs)
0128       nTracks += std::accumulate(tracks.begin(), tracks.end(), 0, valid);
0129     tracks_.reserve(nTracks);
0130     // convert input data
0131     for (int region = 0; region < setup_->numRegions(); region++) {
0132       const int offsetTFP = region * setup_->tfpNumChannel();
0133       const int offsetStub = region * setup_->numLayers();
0134       const tt::StreamTrack& streamKF = inputs[region];
0135       const tt::Stream& streamTQ = inputsAdd[region];
0136       for (int channel = 0; channel < setup_->tfpNumChannel(); channel++)
0137         outputs[offsetTFP + channel] = std::deque<Track*>(streamKF.size(), nullptr);
0138       for (int frame = 0; frame < (int)streamKF.size(); frame++) {
0139         const tt::FrameTrack& frameTrack = streamKF[frame];
0140         const tt::Frame& frameTQ = streamTQ[frame];
0141         if (frameTrack.first.isNull())
0142           continue;
0143         std::vector<TTStubRef> ttStubRefs;
0144         ttStubRefs.reserve(setup_->numLayers());
0145         for (int layer = 0; layer < setup_->numLayers(); layer++) {
0146           const TTStubRef& ttStubRef = stubs[offsetStub + layer][frame].first;
0147           if (ttStubRef.isNonnull())
0148             ttStubRefs.push_back(ttStubRef);
0149         }
0150         tracks_.emplace_back(frameTrack, frameTQ, ttStubRefs, dataFormats_, trackQuality_);
0151         Track& track = tracks_.back();
0152         outputs[offsetTFP + track.channel_][frame] = track.valid_ ? &track : nullptr;
0153       }
0154       // remove all gaps between end and last track
0155       for (int channel = 0; channel < setup_->tfpNumChannel(); channel++) {
0156         std::deque<Track*> input = outputs[offsetTFP + channel];
0157         for (auto it = input.end(); it != input.begin();)
0158           it = (*--it) ? input.begin() : input.erase(it);
0159       }
0160     }
0161   }
0162 
0163   // emualte data format f/w
0164   void TrackFindingProcessor::produce(std::vector<std::deque<Track*>>& inputs, tt::StreamsTrack& outputs) const {
0165     for (int channel = 0; channel < static_cast<int>(inputs.size()); channel++) {
0166       std::deque<Track*>& input = inputs[channel];
0167       std::deque<PartialFrameTrack> stack;
0168       std::deque<tt::FrameTrack> output;
0169       // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
0170       while (!input.empty() || !stack.empty()) {
0171         output.emplace_back(tt::FrameTrack());
0172         tt::FrameTrack& frame = output.back();
0173         Track* track = pop_front(input);
0174         if (track)
0175           for (const PartialFrame& pf : track->partials_)
0176             stack.emplace_back(track->ttTrackRef_, pf);
0177         TTBV ttBV;
0178         for (int i = 0; i < partial_out; i++) {
0179           if (stack.empty()) {
0180             ttBV += TTBV(0, partial_width);
0181             continue;
0182           }
0183           const PartialFrameTrack& pft = stack.front();
0184           frame.first = pft.first;
0185           ttBV += TTBV(pft.second.to_string());
0186           stack.pop_front();
0187         }
0188         frame.second = ttBV.bs();
0189       }
0190       // perorm truncation
0191       if (setup_->enableTruncation() && static_cast<int>(output.size()) > setup_->numFramesIOHigh())
0192         output.resize(setup_->numFramesIOHigh());
0193       outputs[channel] = tt::StreamTrack(output.begin(), output.end());
0194     }
0195   }
0196 
0197   // produce TTTracks
0198   void TrackFindingProcessor::produce(const tt::StreamsTrack& inputs, tt::TTTracks& outputs) const {
0199     // collect input TTTrackRefs
0200     std::vector<TTTrackRef> ttTrackRefs;
0201     ttTrackRefs.reserve(tracks_.size());
0202     const TTTrack<Ref_Phase2TrackerDigi_>* last = nullptr;
0203     for (const tt::StreamTrack& stream : inputs) {
0204       for (const tt::FrameTrack& frame : stream) {
0205         const TTTrackRef& ttTrackRef = frame.first;
0206         if (frame.first.isNull() || last == ttTrackRef.get())
0207           continue;
0208         last = ttTrackRef.get();
0209         ttTrackRefs.push_back(ttTrackRef);
0210       }
0211     }
0212     // convert input TTTrackRefs into output TTTracks
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(ttTrackRef->etaSector());
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 trklet