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
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
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
0105 void TrackFindingProcessor::produce(const tt::StreamsTrack& inputs,
0106 const tt::StreamsStub& stubs,
0107 tt::TTTracks& ttTracks,
0108 tt::StreamsTrack& outputs) {
0109
0110 std::vector<std::deque<Track*>> streams(outputs.size());
0111 consume(inputs, stubs, streams);
0112
0113 produce(streams, outputs);
0114
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
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
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
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
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
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
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
0197 void TrackFindingProcessor::produce(const tt::StreamsTrack& inputs, tt::TTTracks& outputs) const {
0198
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
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
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
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
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 }