Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:13:51

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