Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:58

0001 #include "L1Trigger/TrackFindingTracklet/interface/DRin.h"
0002 
0003 #include <vector>
0004 #include <deque>
0005 #include <numeric>
0006 #include <algorithm>
0007 
0008 using namespace std;
0009 using namespace edm;
0010 using namespace tt;
0011 using namespace trackerTFP;
0012 
0013 namespace trklet {
0014 
0015   DRin::DRin(const ParameterSet& iConfig,
0016              const Setup* setup,
0017              const DataFormats* dataFormats,
0018              const LayerEncoding* layerEncoding,
0019              const ChannelAssignment* channelAssignment,
0020              const Settings* settings,
0021              int region)
0022       : enableTruncation_(iConfig.getParameter<bool>("EnableTruncation")),
0023         useTTStubResiduals_(iConfig.getParameter<bool>("UseTTStubResiduals")),
0024         setup_(setup),
0025         dataFormats_(dataFormats),
0026         layerEncoding_(layerEncoding),
0027         channelAssignment_(channelAssignment),
0028         settings_(settings),
0029         region_(region),
0030         input_(channelAssignment_->numChannelsTrack()),
0031         // unified tracklet digitisation granularity
0032         baseUinv2R_(.5 * settings_->kphi1() / settings_->kr() * pow(2, settings_->rinv_shift())),
0033         baseUphiT_(settings_->kphi1() * pow(2, settings_->phi0_shift())),
0034         baseUcot_(settings_->kz() / settings_->kr() * pow(2, settings_->t_shift())),
0035         baseUzT_(settings_->kz() * pow(2, settings_->z0_shift())),
0036         baseUr_(settings_->kr()),
0037         baseUphi_(settings_->kphi1()),
0038         baseUz_(settings_->kz()),
0039         // KF input format digitisation granularity (identical to TMTT)
0040         baseLinv2R_(dataFormats->base(Variable::inv2R, Process::kfin)),
0041         baseLphiT_(dataFormats->base(Variable::phiT, Process::kfin)),
0042         baseLcot_(dataFormats->base(Variable::cot, Process::kfin)),
0043         baseLzT_(dataFormats->base(Variable::zT, Process::kfin)),
0044         baseLr_(dataFormats->base(Variable::r, Process::kfin)),
0045         baseLphi_(dataFormats->base(Variable::phi, Process::kfin)),
0046         baseLz_(dataFormats->base(Variable::z, Process::kfin)),
0047         // Finer granularity (by powers of 2) than the TMTT one. Used to transform from Tracklet to TMTT base.
0048         baseHinv2R_(baseLinv2R_ * pow(2, floor(log2(baseUinv2R_ / baseLinv2R_)))),
0049         baseHphiT_(baseLphiT_ * pow(2, floor(log2(baseUphiT_ / baseLphiT_)))),
0050         baseHcot_(baseLcot_ * pow(2, floor(log2(baseUcot_ / baseLcot_)))),
0051         baseHzT_(baseLzT_ * pow(2, floor(log2(baseUzT_ / baseLzT_)))),
0052         baseHr_(baseLr_ * pow(2, floor(log2(baseUr_ / baseLr_)))),
0053         baseHphi_(baseLphi_ * pow(2, floor(log2(baseUphi_ / baseLphi_)))),
0054         baseHz_(baseLz_ * pow(2, floor(log2(baseUz_ / baseLz_)))) {
0055     // calculate digitisation granularity used for inverted cot(theta)
0056     const int baseShiftInvCot = ceil(log2(setup_->outerRadius() / setup_->hybridRangeR())) - setup_->widthDSPbu();
0057     baseInvCot_ = pow(2, baseShiftInvCot);
0058   }
0059 
0060   // read in and organize input tracks and stubs
0061   void DRin::consume(const StreamsTrack& streamsTrack, const StreamsStub& streamsStub) {
0062     static const double maxCot = sinh(setup_->maxEta()) + setup_->beamWindowZ() / setup_->chosenRofZ();
0063     static const int unusedMSBcot = floor(log2(baseUcot_ * pow(2, settings_->nbitst()) / (2. * maxCot)));
0064     static const double baseCot =
0065         baseUcot_ * pow(2, settings_->nbitst() - unusedMSBcot - 1 - setup_->widthAddrBRAM18());
0066     const int offsetTrack = region_ * channelAssignment_->numChannelsTrack();
0067     // count tracks and stubs to reserve container
0068     int nTracks(0);
0069     int nStubs(0);
0070     for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) {
0071       const int channelTrack = offsetTrack + channel;
0072       const int offsetStub = channelAssignment_->offsetStub(channelTrack);
0073       const StreamTrack& streamTrack = streamsTrack[channelTrack];
0074       input_[channel].reserve(streamTrack.size());
0075       for (int frame = 0; frame < (int)streamTrack.size(); frame++) {
0076         if (streamTrack[frame].first.isNull())
0077           continue;
0078         nTracks++;
0079         for (int layer = 0; layer < channelAssignment_->numProjectionLayers(channel); layer++)
0080           if (streamsStub[offsetStub + layer][frame].first.isNonnull())
0081             nStubs++;
0082       }
0083     }
0084     stubs_.reserve(nStubs + nTracks * channelAssignment_->numSeedingLayers());
0085     tracks_.reserve(nTracks);
0086     // store tracks and stubs
0087     for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) {
0088       const int channelTrack = offsetTrack + channel;
0089       const int offsetStub = channelAssignment_->offsetStub(channelTrack);
0090       const StreamTrack& streamTrack = streamsTrack[channelTrack];
0091       vector<Track*>& input = input_[channel];
0092       for (int frame = 0; frame < (int)streamTrack.size(); frame++) {
0093         const TTTrackRef& ttTrackRef = streamTrack[frame].first;
0094         if (ttTrackRef.isNull()) {
0095           input.push_back(nullptr);
0096           continue;
0097         }
0098         //convert track parameter
0099         const double r2Inv = digi(-ttTrackRef->rInv() / 2., baseUinv2R_);
0100         const double phi0U =
0101             digi(tt::deltaPhi(ttTrackRef->phi() - region_ * setup_->baseRegion() + setup_->hybridRangePhi() / 2.),
0102                  baseUphiT_);
0103         const double phi0S = digi(phi0U - setup_->hybridRangePhi() / 2., baseUphiT_);
0104         const double cot = digi(ttTrackRef->tanL(), baseUcot_);
0105         const double z0 = digi(ttTrackRef->z0(), baseUzT_);
0106         const double phiT = digi(phi0S + r2Inv * digi(dataFormats_->chosenRofPhi(), baseUr_), baseUphiT_);
0107         const double zT = digi(z0 + cot * digi(setup_->chosenRofZ(), baseUr_), baseUzT_);
0108         // kill tracks outside of fiducial range
0109         if (abs(phiT) > setup_->baseRegion() / 2. || abs(zT) > setup_->hybridMaxCot() * setup_->chosenRofZ() ||
0110             abs(z0) > setup_->beamWindowZ()) {
0111           input.push_back(nullptr);
0112           continue;
0113         }
0114         // convert stubs
0115         vector<Stub*> stubs;
0116         stubs.reserve(channelAssignment_->numProjectionLayers(channel) + channelAssignment_->numSeedingLayers());
0117         for (int layer = 0; layer < channelAssignment_->numProjectionLayers(channel); layer++) {
0118           const FrameStub& frameStub = streamsStub[offsetStub + layer][frame];
0119           const TTStubRef& ttStubRef = frameStub.first;
0120           if (ttStubRef.isNull())
0121             continue;
0122           const int layerId = channelAssignment_->layerId(channel, layer);
0123           // parse residuals from tt::Frame and take r and layerId from tt::TTStubRef
0124           const bool barrel = setup_->barrel(ttStubRef);
0125           const int layerIdTracklet = setup_->trackletLayerId(ttStubRef);
0126           const double basePhi = barrel ? settings_->kphi1() : settings_->kphi(layerIdTracklet);
0127           const double baseRZ = barrel ? settings_->kz(layerIdTracklet) : settings_->kz();
0128           const int widthRZ = barrel ? settings_->zresidbits() : settings_->rresidbits();
0129           TTBV hw(frameStub.second);
0130           const TTBV hwRZ(hw, widthRZ, 0, true);
0131           hw >>= widthRZ;
0132           const TTBV hwPhi(hw, settings_->phiresidbits(), 0, true);
0133           hw >>= settings_->phiresidbits();
0134           const int indexLayerId = setup_->indexLayerId(ttStubRef);
0135           const SensorModule::Type type = setup_->type(ttStubRef);
0136           const int widthR = setup_->tbWidthR(type);
0137           const double baseR = setup_->hybridBaseR(type);
0138           const TTBV hwR(hw, widthR, 0, barrel);
0139           hw >>= widthR;
0140           double r = hwR.val(baseR) + (barrel ? setup_->hybridLayerR(indexLayerId) : 0.);
0141           if (type == SensorModule::Disk2S)
0142             r = setup_->disk2SR(indexLayerId, r);
0143           r = digi(r - dataFormats_->chosenRofPhi(), baseUr_);
0144           double phi = hwPhi.val(basePhi);
0145           if (basePhi > baseUphi_)
0146             phi += baseUphi_ / 2.;
0147           const double z = digi(hwRZ.val(baseRZ) * (barrel ? 1. : -cot), baseUz_);
0148           const TTBV hwStubId(hw, channelAssignment_->widthSeedStubId(), 0, false);
0149           const int stubId = hwStubId.val();
0150           // determine module type
0151           bool psTilt;
0152           if (barrel) {
0153             const double posZ = (r + digi(dataFormats_->chosenRofPhi(), baseUr_)) * cot + z0 + z;
0154             const int indexLayerId = setup_->indexLayerId(ttStubRef);
0155             const double limit = setup_->tiltedLayerLimitZ(indexLayerId);
0156             psTilt = abs(posZ) < limit;
0157           } else
0158             psTilt = setup_->psModule(ttStubRef);
0159           if (useTTStubResiduals_) {
0160             const GlobalPoint gp = setup_->stubPos(ttStubRef);
0161             const double ttR = r;
0162             const double ttZ = gp.z() - (z0 + (ttR + dataFormats_->chosenRofPhi()) * cot);
0163             stubs_.emplace_back(ttStubRef, layerId, layerIdTracklet, false, stubId, ttR, phi, ttZ, psTilt);
0164           } else
0165             stubs_.emplace_back(ttStubRef, layerId, layerIdTracklet, false, stubId, r, phi, z, psTilt);
0166           stubs.push_back(&stubs_.back());
0167         }
0168         // create fake seed stubs, since TrackBuilder doesn't output these stubs, required by the KF.
0169         for (int seedingLayer = 0; seedingLayer < channelAssignment_->numSeedingLayers(); seedingLayer++) {
0170           const int channelStub = channelAssignment_->numProjectionLayers(channel) + seedingLayer;
0171           const FrameStub& frameStub = streamsStub[offsetStub + channelStub][frame];
0172           const TTStubRef& ttStubRef = frameStub.first;
0173           if (ttStubRef.isNull())
0174             continue;
0175           const int layerId = channelAssignment_->layerId(channel, channelStub);
0176           const int layerIdTracklet = setup_->trackletLayerId(ttStubRef);
0177           const int stubId = TTBV(frameStub.second).val(channelAssignment_->widthSeedStubId());
0178           const bool barrel = setup_->barrel(ttStubRef);
0179           double r;
0180           if (barrel)
0181             r = digi(setup_->hybridLayerR(layerId - setup_->offsetLayerId()) - dataFormats_->chosenRofPhi(), baseUr_);
0182           else {
0183             r = (z0 +
0184                  digi(setup_->hybridDiskZ(layerId - setup_->offsetLayerId() - setup_->offsetLayerDisks()), baseUzT_)) *
0185                 digi(1. / digi(abs(cot), baseCot), baseInvCot_);
0186             r = digi(r - digi(dataFormats_->chosenRofPhi(), baseUr_), baseUr_);
0187           }
0188           static constexpr double phi = 0.;
0189           static constexpr double z = 0.;
0190           // determine module type
0191           bool psTilt;
0192           if (barrel) {
0193             const double posZ =
0194                 digi(digi(setup_->hybridLayerR(layerId - setup_->offsetLayerId()), baseUr_) * cot + z0, baseUz_);
0195             const int indexLayerId = setup_->indexLayerId(ttStubRef);
0196             const double limit = digi(setup_->tiltedLayerLimitZ(indexLayerId), baseUz_);
0197             psTilt = abs(posZ) < limit;
0198           } else
0199             psTilt = true;
0200           const GlobalPoint gp = setup_->stubPos(ttStubRef);
0201           const double ttR = gp.perp() - dataFormats_->chosenRofPhi();
0202           const double ttZ = gp.z() - (z0 + (ttR + dataFormats_->chosenRofPhi()) * cot);
0203           if (useTTStubResiduals_)
0204             stubs_.emplace_back(ttStubRef, layerId, layerIdTracklet, true, stubId, ttR, phi, ttZ, psTilt);
0205           else
0206             stubs_.emplace_back(ttStubRef, layerId, layerIdTracklet, true, stubId, r, phi, z, psTilt);
0207           stubs.push_back(&stubs_.back());
0208         }
0209         const bool valid = frame < setup_->numFrames() ? true : enableTruncation_;
0210         tracks_.emplace_back(ttTrackRef, valid, r2Inv, phiT, cot, zT, stubs);
0211         input.push_back(&tracks_.back());
0212       }
0213     }
0214   }
0215 
0216   // fill output products
0217   void DRin::produce(StreamsStub& accpetedStubs,
0218                      StreamsTrack& acceptedTracks,
0219                      StreamsStub& lostStubs,
0220                      StreamsTrack& lostTracks) {
0221     // base transform into high precision TMTT format
0222     for (Track& track : tracks_) {
0223       track.inv2R_ = redigi(track.inv2R_, baseUinv2R_, baseHinv2R_, setup_->widthDSPbu());
0224       track.phiT_ = redigi(track.phiT_, baseUphiT_, baseHphiT_, setup_->widthDSPbu());
0225       track.cot_ = redigi(track.cot_, baseUcot_, baseHcot_, setup_->widthDSPbu());
0226       track.zT_ = redigi(track.zT_, baseUzT_, baseHzT_, setup_->widthDSPbu());
0227       for (Stub* stub : track.stubs_) {
0228         stub->r_ = redigi(stub->r_, baseUr_, baseHr_, setup_->widthDSPbu());
0229         stub->phi_ = redigi(stub->phi_, baseUphi_, baseHphi_, setup_->widthDSPbu());
0230         stub->z_ = redigi(stub->z_, baseUz_, baseHz_, setup_->widthDSPbu());
0231       }
0232     }
0233     // find sector
0234     for (Track& track : tracks_) {
0235       const int sectorPhi = track.phiT_ < 0. ? 0 : 1;
0236       track.phiT_ -= (sectorPhi - .5) * setup_->baseSector();
0237       int sectorEta(-1);
0238       for (; sectorEta < setup_->numSectorsEta(); sectorEta++)
0239         if (track.zT_ < digi(setup_->chosenRofZ() * sinh(setup_->boundarieEta(sectorEta + 1)), baseHzT_))
0240           break;
0241       if (sectorEta >= setup_->numSectorsEta() || sectorEta <= -1) {
0242         track.valid_ = false;
0243         continue;
0244       }
0245       track.cot_ = track.cot_ - digi(setup_->sectorCot(sectorEta), baseHcot_);
0246       track.zT_ = track.zT_ - digi(setup_->chosenRofZ() * setup_->sectorCot(sectorEta), baseHzT_);
0247       track.sector_ = sectorPhi * setup_->numSectorsEta() + sectorEta;
0248     }
0249     // base transform into TMTT format
0250     for (Track& track : tracks_) {
0251       if (!track.valid_)
0252         continue;
0253       // store track parameter shifts
0254       const double dinv2R = digi(track.inv2R_ - digi(track.inv2R_, baseLinv2R_), baseHinv2R_);
0255       const double dphiT = digi(track.phiT_ - digi(track.phiT_, baseLphiT_), baseHphiT_);
0256       const double dcot = digi(track.cot_ - digi(track.cot_, baseLcot_), baseHcot_);
0257       const double dzT = digi(track.zT_ - digi(track.zT_, baseLzT_), baseHzT_);
0258       // shift track parameter;
0259       track.inv2R_ = digi(track.inv2R_, baseLinv2R_);
0260       track.phiT_ = digi(track.phiT_, baseLphiT_);
0261       track.cot_ = digi(track.cot_, baseLcot_);
0262       track.zT_ = digi(track.zT_, baseLzT_);
0263       // range checks
0264       if (!dataFormats_->format(Variable::inv2R, Process::kfin).inRange(track.inv2R_, true))
0265         track.valid_ = false;
0266       if (!dataFormats_->format(Variable::phiT, Process::kfin).inRange(track.phiT_, true))
0267         track.valid_ = false;
0268       if (!dataFormats_->format(Variable::cot, Process::kfin).inRange(track.cot_, true))
0269         track.valid_ = false;
0270       if (!dataFormats_->format(Variable::zT, Process::kfin).inRange(track.zT_, true))
0271         track.valid_ = false;
0272       if (!track.valid_)
0273         continue;
0274       // adjust stub residuals by track parameter shifts
0275       for (Stub* stub : track.stubs_) {
0276         const double dphi = digi(dphiT + stub->r_ * dinv2R, baseHphi_);
0277         const double r = stub->r_ + digi(dataFormats_->chosenRofPhi() - setup_->chosenRofZ(), baseHr_);
0278         const double dz = digi(dzT + r * dcot, baseHz_);
0279         stub->phi_ = digi(stub->phi_ + dphi, baseLphi_);
0280         stub->z_ = digi(stub->z_ + dz, baseLz_);
0281         // range checks
0282         if (!dataFormats_->format(Variable::phi, Process::kfin).inRange(stub->phi_))
0283           stub->valid_ = false;
0284         if (!dataFormats_->format(Variable::z, Process::kfin).inRange(stub->z_))
0285           stub->valid_ = false;
0286       }
0287     }
0288     // encode layer id
0289     for (Track& track : tracks_) {
0290       if (!track.valid_)
0291         continue;
0292       const int sectorEta = track.sector_ % setup_->numSectorsEta();
0293       const int zT = dataFormats_->format(Variable::zT, Process::kfin).toUnsigned(track.zT_);
0294       const int cot = dataFormats_->format(Variable::cot, Process::kfin).toUnsigned(track.cot_);
0295       for (Stub* stub : track.stubs_) {
0296         if (!stub->valid_)
0297           continue;
0298         // store encoded layerId
0299         stub->layerKF_ = layerEncoding_->layerIdKF(sectorEta, zT, cot, stub->layer_);
0300         // kill stubs from layers which can't be crossed by track
0301         if (stub->layerKF_ == -1)
0302           stub->valid_ = false;
0303       }
0304       TTBV hitPattern(0, setup_->numLayers());
0305       // kill multiple stubs from same kf layer
0306       for (Stub* stub : track.stubs_) {
0307         if (!stub->valid_)
0308           continue;
0309         if (hitPattern[stub->layerKF_])
0310           stub->valid_ = false;
0311         else
0312           hitPattern.set(stub->layerKF_);
0313       }
0314       // lookup maybe layers
0315       track.maybe_ = layerEncoding_->maybePattern(sectorEta, zT, cot);
0316     }
0317     // kill tracks with not enough layer
0318     for (Track& track : tracks_) {
0319       if (!track.valid_)
0320         continue;
0321       TTBV hits(0, setup_->numLayers());
0322       for (const Stub* stub : track.stubs_)
0323         if (stub->valid_)
0324           hits.set(stub->layerKF_);
0325       if (hits.count() < setup_->kfMinLayers())
0326         track.valid_ = false;
0327     }
0328     // store helper
0329     auto frameTrack = [this](Track* track) {
0330       const TTBV sectorPhi(
0331           dataFormats_->format(Variable::sectorPhi, Process::kfin).ttBV(track->sector_ / setup_->numSectorsEta()));
0332       const TTBV sectorEta(
0333           dataFormats_->format(Variable::sectorEta, Process::kfin).ttBV(track->sector_ % setup_->numSectorsEta()));
0334       const TTBV inv2R(dataFormats_->format(Variable::inv2R, Process::kfin).ttBV(track->inv2R_));
0335       const TTBV phiT(dataFormats_->format(Variable::phiT, Process::kfin).ttBV(track->phiT_));
0336       const TTBV cot(dataFormats_->format(Variable::cot, Process::kfin).ttBV(track->cot_));
0337       const TTBV zT(dataFormats_->format(Variable::zT, Process::kfin).ttBV(track->zT_));
0338       return FrameTrack(
0339           track->ttTrackRef_,
0340           Frame("1" + sectorPhi.str() + sectorEta.str() + inv2R.str() + phiT.str() + zT.str() + cot.str()));
0341     };
0342     auto frameStub = [this](Track* track, int layer) {
0343       auto equal = [layer](Stub* stub) { return stub->valid_ && stub->layerKF_ == layer; };
0344       const auto it = find_if(track->stubs_.begin(), track->stubs_.end(), equal);
0345       if (it == track->stubs_.end() || !(*it)->valid_)
0346         return FrameStub();
0347       Stub* stub = *it;
0348       const TTBV layerId(stub->layerDet_, channelAssignment_->widthLayerId());
0349       const TTBV stubId(stub->stubId_, channelAssignment_->widthSeedStubId(), true);
0350       const TTBV r(dataFormats_->format(Variable::r, Process::kfin).ttBV(stub->r_));
0351       const TTBV phi(dataFormats_->format(Variable::phi, Process::kfin).ttBV(stub->phi_));
0352       const TTBV z(dataFormats_->format(Variable::z, Process::kfin).ttBV(stub->z_));
0353       return FrameStub(
0354           stub->ttStubRef_,
0355           Frame("1" + to_string(stub->psTilt_) + layerId.str() + stubId.str() + r.str() + phi.str() + z.str()));
0356     };
0357     // route tracks into pt bins and store result
0358     const int offsetTrack = region_ * channelAssignment_->numNodesDR();
0359     for (int nodeDR = 0; nodeDR < channelAssignment_->numNodesDR(); nodeDR++) {
0360       deque<Track*> accepted;
0361       deque<Track*> lost;
0362       vector<deque<Track*>> stacks(channelAssignment_->numChannelsTrack());
0363       vector<deque<Track*>> inputs(channelAssignment_->numChannelsTrack());
0364       for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) {
0365         for (Track* track : input_[channel]) {
0366           const bool match = track && channelAssignment_->nodeDR(track->ttTrackRef_) == nodeDR;
0367           if (match && !track->valid_)
0368             lost.push_back(track);
0369           inputs[channel].push_back(match && track->valid_ ? track : nullptr);
0370         }
0371       }
0372       // remove all gaps between end and last track
0373       for (deque<Track*>& input : inputs)
0374         for (auto it = input.end(); it != input.begin();)
0375           it = (*--it) ? input.begin() : input.erase(it);
0376       // clock accurate firmware emulation, each while trip describes one clock tick, one stub in and one stub out per tick
0377       while (!all_of(inputs.begin(), inputs.end(), [](const deque<Track*>& tracks) { return tracks.empty(); }) or
0378              !all_of(stacks.begin(), stacks.end(), [](const deque<Track*>& tracks) { return tracks.empty(); })) {
0379         // fill input fifos
0380         for (int channel = 0; channel < channelAssignment_->numChannelsTrack(); channel++) {
0381           deque<Track*>& stack = stacks[channel];
0382           Track* track = pop_front(inputs[channel]);
0383           if (track) {
0384             if (enableTruncation_ && (int)stack.size() == channelAssignment_->depthMemory() - 1)
0385               lost.push_back(pop_front(stack));
0386             stack.push_back(track);
0387           }
0388         }
0389         // merge input fifos to one stream, prioritizing higher input channel over lower channel
0390         bool nothingToRoute(true);
0391         for (int channel = channelAssignment_->numChannelsTrack() - 1; channel >= 0; channel--) {
0392           Track* track = pop_front(stacks[channel]);
0393           if (track) {
0394             nothingToRoute = false;
0395             accepted.push_back(track);
0396             break;
0397           }
0398         }
0399         if (nothingToRoute)
0400           accepted.push_back(nullptr);
0401       }
0402       // truncate if desired
0403       if (enableTruncation_ && (int)accepted.size() > setup_->numFrames()) {
0404         const auto limit = next(accepted.begin(), setup_->numFrames());
0405         copy_if(limit, accepted.end(), back_inserter(lost), [](const Track* track) { return track; });
0406         accepted.erase(limit, accepted.end());
0407       }
0408       // remove all gaps between end and last track
0409       for (auto it = accepted.end(); it != accepted.begin();)
0410         it = (*--it) ? accepted.begin() : accepted.erase(it);
0411       // fill products StreamsStub& accpetedStubs, StreamsTrack& acceptedTracks, StreamsStub& lostStubs, StreamsTrack& lostTracks
0412       const int channelTrack = offsetTrack + nodeDR;
0413       const int offsetStub = channelTrack * setup_->numLayers();
0414       // fill lost tracks and stubs without gaps
0415       lostTracks[channelTrack].reserve(lost.size());
0416       for (int layer = 0; layer < setup_->numLayers(); layer++)
0417         lostStubs[offsetStub + layer].reserve(lost.size());
0418       for (Track* track : lost) {
0419         lostTracks[channelTrack].emplace_back(frameTrack(track));
0420         for (int layer = 0; layer < setup_->numLayers(); layer++)
0421           lostStubs[offsetStub + layer].emplace_back(frameStub(track, layer));
0422       }
0423       // fill accepted tracks and stubs with gaps
0424       acceptedTracks[channelTrack].reserve(accepted.size());
0425       for (int layer = 0; layer < setup_->numLayers(); layer++)
0426         accpetedStubs[offsetStub + layer].reserve(accepted.size());
0427       for (Track* track : accepted) {
0428         if (!track) {  // fill gap
0429           acceptedTracks[channelTrack].emplace_back(FrameTrack());
0430           for (int layer = 0; layer < setup_->numLayers(); layer++)
0431             accpetedStubs[offsetStub + layer].emplace_back(FrameStub());
0432           continue;
0433         }
0434         acceptedTracks[channelTrack].emplace_back(frameTrack(track));
0435         for (int layer = 0; layer < setup_->numLayers(); layer++)
0436           accpetedStubs[offsetStub + layer].emplace_back(frameStub(track, layer));
0437       }
0438     }
0439   }
0440 
0441   // remove and return first element of deque, returns nullptr if empty
0442   template <class T>
0443   T* DRin::pop_front(deque<T*>& ts) const {
0444     T* t = nullptr;
0445     if (!ts.empty()) {
0446       t = ts.front();
0447       ts.pop_front();
0448     }
0449     return t;
0450   }
0451 
0452   // basetransformation of val from baseLow into baseHigh using widthMultiplier bit multiplication
0453   double DRin::redigi(double val, double baseLow, double baseHigh, int widthMultiplier) const {
0454     const double base = pow(2, 1 - widthMultiplier);
0455     const double transform = digi(baseLow / baseHigh, base);
0456     return (floor(val * transform / baseLow) + .5) * baseHigh;
0457   }
0458 
0459 }  // namespace trklet