Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "FWCore/Framework/interface/stream/EDProducer.h"
0002 #include "FWCore/Framework/interface/Run.h"
0003 #include "FWCore/Framework/interface/EventSetup.h"
0004 #include "FWCore/Framework/interface/Event.h"
0005 #include "FWCore/Framework/interface/MakerMacros.h"
0006 #include "FWCore/Utilities/interface/EDGetToken.h"
0007 #include "FWCore/Utilities/interface/EDPutToken.h"
0008 #include "FWCore/Utilities/interface/ESGetToken.h"
0009 #include "FWCore/Utilities/interface/InputTag.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "DataFormats/Common/interface/Handle.h"
0012 
0013 #include "L1Trigger/TrackTrigger/interface/Setup.h"
0014 #include "L1Trigger/TrackerTFP/interface/DataFormats.h"
0015 #include "L1Trigger/TrackTrigger/interface/L1TrackQuality.h"
0016 
0017 #include <string>
0018 #include <numeric>
0019 
0020 using namespace std;
0021 using namespace edm;
0022 using namespace trackerTFP;
0023 using namespace tt;
0024 
0025 namespace trklet {
0026 
0027   /*! \class  trklet::ProducerKFout
0028    *  \brief  Converts KF output into TFP output
0029    *  A bit accurate emulation of the track transformation, the 
0030    *  eta routing and splitting of the 96-bit track words into 64-bit 
0031    *  packets. Also run is a bit accurate emulation of the track quality
0032    *  BDT, whose output is also added to the track word.
0033    *  \author Christopher Brown
0034    *  \date   2021, Aug
0035    */
0036   class ProducerKFout : public stream::EDProducer<> {
0037   public:
0038     explicit ProducerKFout(const ParameterSet&);
0039     ~ProducerKFout() override {}
0040 
0041   private:
0042     void beginRun(const Run&, const EventSetup&) override;
0043     void produce(Event&, const EventSetup&) override;
0044     void endJob() {}
0045 
0046     // ED input token of kf stubs
0047     EDGetTokenT<StreamsStub> edGetTokenStubs_;
0048     // ED input token of kf tracks
0049     EDGetTokenT<StreamsTrack> edGetTokenTracks_;
0050     // ED input token of kf input to kf output TTTrack map
0051     EDGetTokenT<TTTrackRefMap> edGetTokenTTTrackRefMap_;
0052     // ED output token for accepted kfout tracks
0053     EDPutTokenT<StreamsTrack> edPutTokenAccepted_;
0054     // ED output token for truncated kfout tracks
0055     EDPutTokenT<StreamsTrack> edPutTokenLost_;
0056     // Setup token
0057     ESGetToken<Setup, SetupRcd> esGetTokenSetup_;
0058     // DataFormats token
0059     ESGetToken<DataFormats, DataFormatsRcd> esGetTokenDataFormats_;
0060     // configuration
0061     ParameterSet iConfig_;
0062     // helper class to store configurations
0063     const Setup* setup_;
0064     // helper class to extract structured data from tt::Frames
0065     const DataFormats* dataFormats_;
0066     // Bins for dPhi/dZ use to create weight LUT
0067     vector<double> dPhiBins_;
0068     vector<double> dZBins_;
0069 
0070     std::unique_ptr<L1TrackQuality> trackQualityModel_;
0071     vector<int> tqBins_;
0072     double tqTanlScale_;
0073     double tqZ0Scale_;
0074     static constexpr double ap_fixed_rescale = 32.0;
0075 
0076     // For convenience and keeping readable code, accessed many times
0077     int numWorkers_;
0078 
0079     int partialTrackWordBits_;
0080 
0081     // Helper function to convert floating chi2 to chi2 bin
0082     template <typename T>
0083     unsigned int digitise(const T& bins, double value, double factor) {
0084       unsigned int bin = 0;
0085       for (unsigned int i = 0; i < bins.size() - 1; i++) {
0086         if (value * factor > bins[i] && value * factor <= bins[i + 1])
0087           bin = i;
0088       }
0089       return bin;
0090     }
0091   };
0092 
0093   ProducerKFout::ProducerKFout(const ParameterSet& iConfig) : iConfig_(iConfig) {
0094     const string& labelKF = iConfig.getParameter<string>("LabelKF");
0095     const string& labelAS = iConfig.getParameter<string>("LabelAS");
0096     const string& branchStubs = iConfig.getParameter<string>("BranchAcceptedStubs");
0097     const string& branchTracks = iConfig.getParameter<string>("BranchAcceptedTracks");
0098     const string& branchLost = iConfig.getParameter<string>("BranchLostTracks");
0099     // book in- and output ED products
0100     edGetTokenStubs_ = consumes<StreamsStub>(InputTag(labelKF, branchStubs));
0101     edGetTokenTracks_ = consumes<StreamsTrack>(InputTag(labelKF, branchTracks));
0102     edGetTokenTTTrackRefMap_ = consumes<TTTrackRefMap>(InputTag(labelAS, branchTracks));
0103     edPutTokenAccepted_ = produces<StreamsTrack>(branchTracks);
0104     edPutTokenLost_ = produces<StreamsTrack>(branchLost);
0105     // book ES products
0106     esGetTokenSetup_ = esConsumes<Setup, SetupRcd, Transition::BeginRun>();
0107     esGetTokenDataFormats_ = esConsumes<DataFormats, DataFormatsRcd, Transition::BeginRun>();
0108     // initial ES products
0109     setup_ = nullptr;
0110     dataFormats_ = nullptr;
0111 
0112     trackQualityModel_ = std::make_unique<L1TrackQuality>(iConfig.getParameter<edm::ParameterSet>("TrackQualityPSet"));
0113     edm::ParameterSet trackQualityPSset = iConfig.getParameter<edm::ParameterSet>("TrackQualityPSet");
0114     tqBins_ = trackQualityPSset.getParameter<vector<int>>("tqemu_bins");
0115     tqTanlScale_ = trackQualityPSset.getParameter<double>("tqemu_TanlScale");
0116     tqZ0Scale_ = trackQualityPSset.getParameter<double>("tqemu_Z0Scale");
0117   }
0118 
0119   void ProducerKFout::beginRun(const Run& iRun, const EventSetup& iSetup) {
0120     // helper class to store configurations
0121     setup_ = &iSetup.getData(esGetTokenSetup_);
0122     if (!setup_->configurationSupported())
0123       return;
0124     // check process history if desired
0125     if (iConfig_.getParameter<bool>("CheckHistory"))
0126       setup_->checkHistory(iRun.processHistory());
0127     // helper class to extract structured data from tt::Frames
0128     dataFormats_ = &iSetup.getData(esGetTokenDataFormats_);
0129 
0130     // Calculate 1/dz**2 and 1/dphi**2 bins for v0 and v1 weightings
0131 
0132     float temp_dphi = 0.0;
0133     float temp_dz = 0.0;
0134     for (int i = 0;
0135          i < pow(2, dataFormats_->width(Variable::dPhi, Process::kfin)) / pow(2, setup_->weightBinFraction());
0136          i++) {
0137       temp_dphi =
0138           pow(dataFormats_->base(Variable::dPhi, Process::kfin) * (i + 1) * pow(2, setup_->weightBinFraction()), -2);
0139       temp_dphi = temp_dphi / setup_->dphiTruncation();
0140       temp_dphi = std::floor(temp_dphi);
0141       dPhiBins_.push_back(temp_dphi * setup_->dphiTruncation());
0142     }
0143     for (int i = 0; i < pow(2, dataFormats_->width(Variable::dZ, Process::kfin)) / pow(2, setup_->weightBinFraction());
0144          i++) {
0145       temp_dz =
0146           pow(dataFormats_->base(Variable::dZ, Process::kfin) * (i + 1) * pow(2, setup_->weightBinFraction()), -2);
0147       temp_dz = temp_dz * setup_->dzTruncation();
0148       temp_dz = std::ceil(temp_dz);
0149       dZBins_.push_back(temp_dz / setup_->dzTruncation());
0150     }
0151     numWorkers_ = setup_->kfNumWorker();
0152     partialTrackWordBits_ = TTBV::S_ / 2;
0153   }
0154 
0155   void ProducerKFout::produce(Event& iEvent, const EventSetup& iSetup) {
0156     // empty KFout product
0157     StreamsTrack accepted(setup_->numRegions() * setup_->tfpNumChannel());
0158     StreamsTrack lost(setup_->numRegions() * setup_->tfpNumChannel());
0159     // read in KF Product and produce KFout product
0160     if (setup_->configurationSupported()) {
0161       Handle<StreamsStub> handleStubs;
0162       iEvent.getByToken<StreamsStub>(edGetTokenStubs_, handleStubs);
0163       const StreamsStub& streamsStubs = *handleStubs.product();
0164       Handle<StreamsTrack> handleTracks;
0165       iEvent.getByToken<StreamsTrack>(edGetTokenTracks_, handleTracks);
0166       const StreamsTrack& streamsTracks = *handleTracks.product();
0167       Handle<TTTrackRefMap> handleTTTrackRefMap;
0168       iEvent.getByToken<TTTrackRefMap>(edGetTokenTTTrackRefMap_, handleTTTrackRefMap);
0169       const TTTrackRefMap& ttTrackRefMap = *handleTTTrackRefMap.product();
0170       // 18 Output Links (First Vector) each has a vector of tracks per event (second vector) each track is 3 32 bit TTBV partial tracks
0171       vector<vector<TTBV>> sortedPartialTracks(setup_->numRegions() * setup_->tfpNumChannel(), vector<TTBV>(0));
0172 
0173       TrackKFOutSAPtrCollectionss inTrackStreams;
0174       TrackKFOutSAPtrCollectionss outTrackStreams;
0175 
0176       // Setup empty collections for input tracks to be routed
0177       for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) {
0178         TrackKFOutSAPtrCollections temp_collection;
0179         for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) {
0180           TrackKFOutSAPtrCollection temp;
0181           for (int iTrack = 0; iTrack < setup_->numFramesIO(); iTrack++)
0182             temp.emplace_back(std::make_shared<TrackKFOut>());
0183           temp_collection.push_back(temp);
0184         }
0185         outTrackStreams.push_back(temp_collection);
0186       }
0187 
0188       // Setup empty collections for output tracks from routing
0189       for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) {
0190         TrackKFOutSAPtrCollections temp_collection;
0191         for (int iLink = 0; iLink < numWorkers_; iLink++) {
0192           TrackKFOutSAPtrCollection temp;
0193           for (int iTrack = 0; iTrack < setup_->numFramesIO(); iTrack++)
0194             temp.emplace_back(std::make_shared<TrackKFOut>());
0195           temp_collection.push_back(temp);
0196         }
0197         inTrackStreams.push_back(temp_collection);
0198       }
0199 
0200       StreamsTrack outputStreamsTracks(setup_->numRegions() * setup_->tfpNumChannel());
0201 
0202       // Setup containers for track quality
0203       float tempTQMVA = 0.0;
0204       // Due to ap_fixed implementation in CMSSW this 10,5 must be specified at compile time, TODO make this a changeable parameter
0205       std::vector<ap_fixed<10, 5>> trackQuality_inputs = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
0206 
0207       for (int iLink = 0; iLink < (int)streamsTracks.size(); iLink++) {
0208         for (int iTrack = 0; iTrack < (int)streamsTracks[iLink].size(); iTrack++) {
0209           const auto& track = streamsTracks[iLink].at(iTrack);
0210           TrackKF inTrack(track, dataFormats_);
0211 
0212           double temp_z0 = inTrack.zT() - ((inTrack.cot() * setup_->chosenRofZ()));
0213 
0214           // Correction to Phi calcuation depending if +ve/-ve phi sector
0215           const double baseSectorCorr = inTrack.sectorPhi() ? -setup_->baseSector() : setup_->baseSector();
0216 
0217           double temp_phi0 = inTrack.phiT() - ((inTrack.inv2R()) * setup_->hybridChosenRofPhi()) + baseSectorCorr;
0218 
0219           double temp_tanL = inTrack.cotGlobal();
0220 
0221           TTBV hitPattern(0, setup_->numLayers());
0222 
0223           double tempchi2rphi = 0;
0224           double tempchi2rz = 0;
0225 
0226           int temp_nstub = 0;
0227           int temp_ninterior = 0;
0228           bool counter = false;
0229 
0230           for (int iStub = 0; iStub < setup_->numLayers() - 1; iStub++) {
0231             const auto& stub = streamsStubs[setup_->numLayers() * iLink + iStub].at(iTrack);
0232             StubKF inStub(stub, dataFormats_, iStub);
0233 
0234             if (!stub.first.isNonnull()) {
0235               if (counter)
0236                 temp_ninterior += 1;
0237               continue;
0238             }
0239 
0240             counter = true;
0241 
0242             hitPattern.set(iStub);
0243             temp_nstub += 1;
0244             double phiSquared = pow(inStub.phi(), 2);
0245             double zSquared = pow(inStub.z(), 2);
0246 
0247             double tempv0 = dPhiBins_[(inStub.dPhi() / (dataFormats_->base(Variable::dPhi, Process::kfin) *
0248                                                         pow(2, setup_->weightBinFraction())))];
0249             double tempv1 = dZBins_[(
0250                 inStub.dZ() / (dataFormats_->base(Variable::dZ, Process::kfin) * pow(2, setup_->weightBinFraction())))];
0251 
0252             double tempRphi = phiSquared * tempv0;
0253             double tempRz = zSquared * tempv1;
0254 
0255             tempchi2rphi += tempRphi;
0256             tempchi2rz += tempRz;
0257           }  // Iterate over track stubs
0258 
0259           // Create bit vectors for eacch output, including digitisation of chi2
0260           // TODO implement extraMVA, bendChi2, d0
0261           TTBV trackValid(1, TTTrack_TrackWord::TrackBitWidths::kValidSize, false);
0262           TTBV extraMVA(0, TTTrack_TrackWord::TrackBitWidths::kMVAOtherSize, false);
0263           TTBV bendChi2(0, TTTrack_TrackWord::TrackBitWidths::kBendChi2Size, false);
0264           TTBV chi2rphi(digitise(TTTrack_TrackWord::chi2RPhiBins, tempchi2rphi, (double)setup_->kfoutchi2rphiConv()),
0265                         TTTrack_TrackWord::TrackBitWidths::kChi2RPhiSize,
0266                         false);
0267           TTBV chi2rz(digitise(TTTrack_TrackWord::chi2RZBins, tempchi2rz, (double)setup_->kfoutchi2rzConv()),
0268                       TTTrack_TrackWord::TrackBitWidths::kChi2RZSize,
0269                       false);
0270           TTBV d0(0, TTTrack_TrackWord::TrackBitWidths::kD0Size, false);
0271           TTBV z0(
0272               temp_z0, dataFormats_->base(Variable::zT, Process::kf), TTTrack_TrackWord::TrackBitWidths::kZ0Size, true);
0273           TTBV tanL(temp_tanL,
0274                     dataFormats_->base(Variable::cot, Process::kf),
0275                     TTTrack_TrackWord::TrackBitWidths::kTanlSize,
0276                     true);
0277           TTBV phi0(temp_phi0,
0278                     dataFormats_->base(Variable::phiT, Process::kf),
0279                     TTTrack_TrackWord::TrackBitWidths::kPhiSize,
0280                     true);
0281           TTBV invR(-inTrack.inv2R(),
0282                     dataFormats_->base(Variable::inv2R, Process::kf),
0283                     TTTrack_TrackWord::TrackBitWidths::kRinvSize + 1,
0284                     true);
0285           invR.resize(TTTrack_TrackWord::TrackBitWidths::kRinvSize);
0286 
0287           // Create input vector for BDT
0288           trackQuality_inputs = {
0289               (std::trunc(tanL.val() / tqTanlScale_)) / ap_fixed_rescale,
0290               (std::trunc(z0.val() / tqZ0Scale_)) / ap_fixed_rescale,
0291               0,
0292               temp_nstub,
0293               temp_ninterior,
0294               digitise(TTTrack_TrackWord::chi2RPhiBins, tempchi2rphi, (double)setup_->kfoutchi2rphiConv()),
0295               digitise(TTTrack_TrackWord::chi2RZBins, tempchi2rz, (double)setup_->kfoutchi2rzConv())};
0296 
0297           // Run BDT emulation and package output into 3 bits
0298 
0299           tempTQMVA = trackQualityModel_->runEmulatedTQ(trackQuality_inputs);
0300           tempTQMVA = std::trunc(tempTQMVA * ap_fixed_rescale);
0301           TTBV tqMVA(digitise(tqBins_, tempTQMVA, 1.0), TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize, false);
0302 
0303           // Build 32 bit partial tracks for outputting in 64 bit packets
0304           //                  12 +  3       +  7         +  3    +  6
0305           TTBV partialTrack3((d0 + bendChi2 + hitPattern + tqMVA + extraMVA), partialTrackWordBits_, false);
0306           //                  16   + 12    + 4
0307           TTBV partialTrack2((tanL + z0 + chi2rz), partialTrackWordBits_, false);
0308           //                    1        + 15   +  12 +    4
0309           TTBV partialTrack1((trackValid + invR + phi0 + chi2rphi), partialTrackWordBits_, false);
0310 
0311           int sortKey = (inTrack.sectorEta() < (int)(setup_->numSectorsEta() / 2)) ? 0 : 1;
0312           // Set correct bit to valid for track valid
0313           TrackKFOut temp_track(partialTrack1.set((partialTrackWordBits_ - 1)),
0314                                 partialTrack2,
0315                                 partialTrack3,
0316                                 sortKey,
0317                                 track,
0318                                 iTrack,
0319                                 iLink,
0320                                 true);
0321 
0322           inTrackStreams[iLink / setup_->kfNumWorker()][iLink % setup_->kfNumWorker()][iTrack] =
0323               (std::make_shared<TrackKFOut>(temp_track));
0324         }  // Iterate over Tracks
0325       }    // Iterate over Links
0326            // Route Tracks in eta based on their sort key
0327       for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) {
0328         int buffered_tracks[] = {0, 0};
0329         for (int iTrack = 0; iTrack < setup_->numFramesIO() * ((double)TTBV::S_ / TTTrack_TrackWord::kTrackWordSize);
0330              iTrack++) {
0331           for (int iWorker = 0; iWorker < setup_->kfNumWorker(); iWorker++) {
0332             for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) {
0333               if ((inTrackStreams[iRegion][iWorker][iTrack]->sortKey() == iLink) &&
0334                   (inTrackStreams[iRegion][iWorker][iTrack]->dataValid() == true)) {
0335                 outTrackStreams[iRegion][iLink][buffered_tracks[iLink]] = inTrackStreams[iRegion][iWorker][iTrack];
0336                 buffered_tracks[iLink] = buffered_tracks[iLink] + 1;
0337               }
0338             }
0339           }
0340         }
0341       }
0342 
0343       // Pack output of router onto each link, with correct partial tracks in correct places
0344       for (int iRegion = 0; iRegion < setup_->numRegions(); iRegion++) {
0345         for (int iLink = 0; iLink < setup_->tfpNumChannel(); iLink++) {
0346           for (int iTrack = 0; iTrack < (int)outTrackStreams[iRegion][iLink].size(); iTrack++) {
0347             sortedPartialTracks[2 * iRegion + iLink].push_back(
0348                 outTrackStreams[iRegion][iLink][iTrack]->PartialTrack1());
0349             sortedPartialTracks[2 * iRegion + iLink].push_back(
0350                 outTrackStreams[iRegion][iLink][iTrack]->PartialTrack2());
0351             sortedPartialTracks[2 * iRegion + iLink].push_back(
0352                 outTrackStreams[iRegion][iLink][iTrack]->PartialTrack3());
0353             outputStreamsTracks[2 * iRegion + iLink].emplace_back(outTrackStreams[iRegion][iLink][iTrack]->track());
0354           }
0355         }
0356       }
0357       // Fill products and match up tracks
0358       // store products
0359       const TTBV nullBitTrack(0, partialTrackWordBits_, false);
0360       for (int iLink = 0; iLink < (int)outputStreamsTracks.size(); iLink++) {
0361         // Iterate through partial tracks
0362         int numLinkTracks = (int)outputStreamsTracks[iLink].size();
0363         if (numLinkTracks == 0)
0364           continue;  // Don't fill links if no tracks
0365         if ((numLinkTracks % 2 != 0)) {
0366           sortedPartialTracks[iLink].push_back(nullBitTrack);  //Pad out final set of bits
0367           outputStreamsTracks[iLink].emplace_back(
0368               outputStreamsTracks[iLink][numLinkTracks++]);  //Pad out with final repeated track
0369         }                                                    //If there is an odd number of tracks
0370         for (int iTrack = 0; iTrack < (int)(sortedPartialTracks[iLink].size()); iTrack++) {
0371           if (iTrack % 2 != 1)  // Write to links every other partial track, 3 partial tracks per full TTTrack
0372             continue;
0373           TTTrackRef trackRef;
0374           for (auto& it : ttTrackRefMap) {  //Iterate through ttTrackRefMap to find TTTrackRef Key by a TTTrack Value
0375             if (it.second == outputStreamsTracks[iLink][(int)(iTrack - 1) / 3].first)
0376               trackRef = it.first;
0377           }
0378           if ((int)iTrack / 3 <= setup_->numFramesIO() * ((double)TTBV::S_ / TTTrack_TrackWord::kTrackWordSize))
0379             accepted[iLink].emplace_back(
0380                 std::make_pair(trackRef,
0381                                (sortedPartialTracks[iLink][iTrack - 1].slice(partialTrackWordBits_) +
0382                                 sortedPartialTracks[iLink][iTrack].slice(partialTrackWordBits_))
0383                                    .bs()));
0384           else
0385             lost[iLink].emplace_back(
0386                 std::make_pair(trackRef,
0387                                (sortedPartialTracks[iLink][iTrack - 1].slice(partialTrackWordBits_) +
0388                                 sortedPartialTracks[iLink][iTrack].slice(partialTrackWordBits_))
0389                                    .bs()));
0390         }  //Iterate through sorted partial tracks
0391       }    // Iterate through links
0392     }      // Config Supported
0393     // store products
0394     iEvent.emplace(edPutTokenAccepted_, std::move(accepted));
0395     iEvent.emplace(edPutTokenLost_, std::move(lost));
0396   }
0397 }  // namespace trklet
0398 
0399 DEFINE_FWK_MODULE(trklet::ProducerKFout);