From 7df38541a5c571d4305fa440667b75d9fb820226 Mon Sep 17 00:00:00 2001 From: Dinyar Rabady Date: Mon, 27 Sep 2021 19:57:40 +0200 Subject: [PATCH] (Un)packing of hadronic showers at the uGMT output --- .../implementations_stage2/MuonPacker.cc | 142 ++++++++++++------ .../implementations_stage2/MuonPacker.h | 18 ++- .../L1TMuon/interface/MuonRawDigiTranslator.h | 37 +++-- .../L1TMuon/src/MuonRawDigiTranslator.cc | 51 ++++--- 4 files changed, 163 insertions(+), 85 deletions(-) diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc index f2d62ae8f8470..eb17c3bd77d12 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc @@ -6,14 +6,16 @@ namespace l1t { namespace stage2 { Blocks MuonPacker::pack(const edm::Event& event, const PackerTokens* toks) { - edm::Handle muons; - event.getByToken(static_cast(toks)->getMuonToken(), muons); + GMTOutputObjectMap gmtObjMap; + std::pair muonBx = getMuons(gmtObjMap, event, static_cast(toks)->getMuonToken()); + std::pair muonShowerBx{0, 0}; + if (fedId_ == 1402 && fwId_ >= 0x7000000) { + muonShowerBx = getMuonShowers(gmtObjMap, event, static_cast(toks)->getMuonShowerToken()); + } PayloadMap payloadMap; - for (int bx = muons->getFirstBX(); bx <= muons->getLastBX(); ++bx) { - packBx(payloadMap, muons, bx); - } + packBx(gmtObjMap, muonBx.first, muonBx.second, muonShowerBx.first, muonShowerBx.second, payloadMap); Blocks blocks; // push everything in the blocks vector @@ -23,58 +25,98 @@ namespace l1t { return blocks; } - void MuonPacker::packBx(PayloadMap& payloadMap, const edm::Handle& muons, int bx) { - // the first word in every BX and every block id is 0 - for (unsigned int blkId = b1_; blkId < b1_ + 7; blkId += 2) { - payloadMap[blkId].push_back(0); + std::pair MuonPacker::getMuonShowers(GMTOutputObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& showerToken) { + edm::Handle muonShowers; + event.getByToken(showerToken, muonShowers); + for (int bx = muonShowers->getFirstBX(); bx <= muonShowers->getLastBX(); ++bx) { + if (muonShowers->size(bx) > 0) { + objMap[bx].shower = muonShowers->at(bx, 0); // At most one shower per BX. + } + } + return std::make_pair(muonShowers->getFirstBX(), muonShowers->getLastBX()); + } + + std::pair MuonPacker::getMuons(GMTOutputObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& muonToken) { + edm::Handle muons; + event.getByToken(muonToken, muons); + for (int bx = muons->getFirstBX(); bx <= muons->getLastBX(); ++bx) { + for (auto mu = muons->begin(bx); mu != muons->end(bx); ++mu) { + objMap[bx].mus.push_back(*mu); + } } + return std::make_pair(muons->getFirstBX(), muons->getLastBX()); + } + + void MuonPacker::packBx(const GMTOutputObjectMap& objMap, + const int firstMuonBx, + const int lastMuonBx, + const int firstMuonShowerBx, + const int lastMuonShowerBx, + PayloadMap& payloadMap) { + const auto firstBx{std::min(firstMuonShowerBx, firstMuonBx)}; + const auto lastBx{std::max(lastMuonShowerBx, lastMuonBx)}; + const auto nBx{lastBx - firstBx + 1}; - unsigned int blkId = b1_; - auto mu{muons->begin(bx)}; - uint32_t mu1_shared_word{0}; - uint32_t mu2_shared_word{0}; - uint32_t mu1_msw{0}; - uint32_t mu2_msw{0}; - uint32_t mu1_lsw{0}; - uint32_t mu2_lsw{0}; - // Slightly convoluted logic to account for the Run-3 muon readout record: - // To make space for displacement information we moved the raw - // (i.e. non-extrapolated) eta value to the second "spare" word - // in the block which we call "shared word". So the logic below - // needs to be aware if it is operating on the first or second - // muon in the block in order to place the eta value in the right - // place in the shared word. Additionally the logic needs to - // wait for the second muon in the block before filling the - // payload map because the shared word goes in first. - for (int muCtr = 1; muCtr <= 8; ++muCtr) { - if (mu != muons->end(bx)) { - MuonRawDigiTranslator::generatePackedDataWords( - *mu, mu2_shared_word, mu2_lsw, mu2_msw, fedId_, fwId_, 2 - (muCtr % 2)); - ++mu; + for (int bx{firstBx}; bx < lastBx; ++bx) { + // the first word in every BX and every block id is 0 + for (unsigned int blkId = b1_; blkId < b1_ + 7; blkId += 2) { + payloadMap[blkId].push_back(0); } - // If we're remaining in the current block the muon we just packed is the first one in the block. - // If not we add both muons to the payload map and go to the next block. - if (muCtr % 2 == 1) { - mu1_shared_word = mu2_shared_word; - mu1_lsw = mu2_lsw; - mu1_msw = mu2_msw; - } else { - payloadMap[blkId].push_back(mu1_shared_word | mu2_shared_word); - payloadMap[blkId].push_back(mu1_lsw); - payloadMap[blkId].push_back(mu1_msw); - payloadMap[blkId].push_back(mu2_lsw); - payloadMap[blkId].push_back(mu2_msw); + unsigned int blkId = b1_; + auto mu{objMap.at(bx).mus.begin()}; // Need to get the first muon of that bx from the object map + uint32_t mu1_shared_word{0}; + uint32_t mu2_shared_word{0}; + uint32_t mu1_msw{0}; + uint32_t mu2_msw{0}; + uint32_t mu1_lsw{0}; + uint32_t mu2_lsw{0}; + std::array showerWords{ + MuonRawDigiTranslator::getPackedShowerDataWords(objMap.at(bx).shower, fedId_, fwId_)}; + // Slightly convoluted logic to account for the Run-3 muon readout record: + // To make space for displacement information we moved the raw + // (i.e. non-extrapolated) eta value to the second "spare" word + // in the block which we call "shared word". So the logic below + // needs to be aware if it is operating on the first or second + // muon in the block in order to place the eta value in the right + // place in the shared word. Additionally the logic needs to + // wait for the second muon in the block before filling the + // payload map because the shared word goes in first. + for (int muCtr = 1; muCtr <= 8; ++muCtr) { + if (mu != objMap.at(bx).mus.end()) { + MuonRawDigiTranslator::generatePackedMuonDataWords( + *mu, mu2_shared_word, mu2_lsw, mu2_msw, fedId_, fwId_, 2 - (muCtr % 2)); + ++mu; + } + + // If we're remaining in the current block the muon we just packed is the first one in the block. + // If not we add both muons to the payload map and go to the next block. + if (muCtr % 2 == 1) { + mu1_shared_word = mu2_shared_word; + mu1_lsw = mu2_lsw; + mu1_msw = mu2_msw; + mu1_msw |= showerWords.at(muCtr / 2); // Shower bits are added only to the first muon of the link. + } else { + payloadMap[blkId].push_back(mu1_shared_word | mu2_shared_word); + payloadMap[blkId].push_back(mu1_lsw); + payloadMap[blkId].push_back(mu1_msw); + payloadMap[blkId].push_back(mu2_lsw); + payloadMap[blkId].push_back(mu2_msw); - blkId += 2; + blkId += 2; - mu1_shared_word = 0; - mu1_lsw = 0; - mu1_msw = 0; + mu1_shared_word = 0; + mu1_lsw = 0; + mu1_msw = 0; + } + mu2_shared_word = 0; + mu2_lsw = 0; + mu2_msw = 0; } - mu2_shared_word = 0; - mu2_lsw = 0; - mu2_msw = 0; } } } // namespace stage2 diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.h index 7cb46c12845bb..fe7be55e6421d 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.h @@ -18,9 +18,25 @@ namespace l1t { inline void setFed(unsigned fedId) { fedId_ = fedId; }; private: + struct GMTObjects { + std::vector mus; + MuonShower shower; + }; + typedef std::map GMTOutputObjectMap; // Map of BX --> objects typedef std::map> PayloadMap; - void packBx(PayloadMap& payloadMap, const edm::Handle& muons, int bx); + std::pair getMuonShowers(GMTOutputObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& showerToken); + std::pair getMuons(GMTOutputObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& muonToken); + void packBx(const GMTOutputObjectMap& objMap, + int firstMuonBx, + int lastMuonBx, + int firstMuonShowerBx, + int lastMuonShowerBx, + PayloadMap& payloadMap); unsigned fwId_{0}; unsigned fedId_{0}; diff --git a/L1Trigger/L1TMuon/interface/MuonRawDigiTranslator.h b/L1Trigger/L1TMuon/interface/MuonRawDigiTranslator.h index cd4ee201a89a6..ab7a387019000 100644 --- a/L1Trigger/L1TMuon/interface/MuonRawDigiTranslator.h +++ b/L1Trigger/L1TMuon/interface/MuonRawDigiTranslator.h @@ -2,6 +2,9 @@ #define MuonRawDigiTranslator_h #include "DataFormats/L1Trigger/interface/Muon.h" +#include "DataFormats/L1Trigger/interface/MuonShower.h" + +#include namespace l1t { class MuonRawDigiTranslator { @@ -15,16 +18,17 @@ namespace l1t { int muInBx); static void fillMuon(Muon& mu, uint32_t raw_data_spare, uint64_t dataword, int fed, unsigned int fw, int muInBx); static void fillIntermediateMuon(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63, unsigned int fw); - static void generatePackedDataWords(const Muon& mu, - uint32_t& raw_data_spare, - uint32_t& raw_data_00_31, - uint32_t& raw_data_32_63, - int fedId, - int fwId, - int muInBx); + static void generatePackedMuonDataWords(const Muon& mu, + uint32_t& raw_data_spare, + uint32_t& raw_data_00_31, + uint32_t& raw_data_32_63, + int fedId, + int fwId, + int muInBx); static void generate64bitDataWord( const Muon& mu, uint32_t& raw_data_spare, uint64_t& dataword, int fedId, int fwId, int muInBx); - static int calcHwEta(const uint32_t& raw, const unsigned absEtaShift, const unsigned etaSignShift); + static std::array getPackedShowerDataWords(const MuonShower& shower, int fedId, unsigned int fwId); + static int calcHwEta(const uint32_t& raw, unsigned absEtaShift, unsigned etaSignShift); static constexpr unsigned ptMask_ = 0x1FF; static constexpr unsigned ptShift_ = 10; @@ -49,6 +53,7 @@ namespace l1t { static constexpr unsigned ptUnconstrainedMask_ = 0xFF; static constexpr unsigned ptUnconstrainedShift_ = 21; static constexpr unsigned ptUnconstrainedIntermedidateShift_ = 0; + static constexpr unsigned showerShift_ = 29; // For Run-3 static constexpr unsigned absEtaMu1Shift_ = 13; // For Run-3 static constexpr unsigned etaMu1SignShift_ = 21; // For Run-3 static constexpr unsigned absEtaMu2Shift_ = 22; // For Run-3 @@ -65,14 +70,14 @@ namespace l1t { int muInBx, bool wasSpecialMWGR = false); static void fillIntermediateMuonQuantitiesRun3(Muon& mu, uint32_t raw_data_00_31, uint32_t raw_data_32_63); - static void generatePackedDataWordsRun3(const Muon& mu, - int abs_eta, - int abs_eta_at_vtx, - uint32_t& raw_data_spare, - uint32_t& raw_data_00_31, - uint32_t& raw_data_32_63, - int muInBx, - bool wasSpecialMWGR = false); + static void generatePackedMuonDataWordsRun3(const Muon& mu, + int abs_eta, + int abs_eta_at_vtx, + uint32_t& raw_data_spare, + uint32_t& raw_data_00_31, + uint32_t& raw_data_32_63, + int muInBx, + bool wasSpecialMWGR = false); }; } // namespace l1t diff --git a/L1Trigger/L1TMuon/src/MuonRawDigiTranslator.cc b/L1Trigger/L1TMuon/src/MuonRawDigiTranslator.cc index 79becf8ea8016..b5ed16c019fc1 100644 --- a/L1Trigger/L1TMuon/src/MuonRawDigiTranslator.cc +++ b/L1Trigger/L1TMuon/src/MuonRawDigiTranslator.cc @@ -177,13 +177,13 @@ void l1t::MuonRawDigiTranslator::fillIntermediateMuonQuantitiesRun3(Muon& mu, mu.setHwPtUnconstrained((raw_data_00_31 >> ptUnconstrainedIntermedidateShift_) & ptUnconstrainedMask_); } -void l1t::MuonRawDigiTranslator::generatePackedDataWords(const Muon& mu, - uint32_t& raw_data_spare, - uint32_t& raw_data_00_31, - uint32_t& raw_data_32_63, - const int fedID, - const int fwID, - const int muInBx) { +void l1t::MuonRawDigiTranslator::generatePackedMuonDataWords(const Muon& mu, + uint32_t& raw_data_spare, + uint32_t& raw_data_00_31, + uint32_t& raw_data_32_63, + const int fedID, + const int fwID, + const int muInBx) { int abs_eta = mu.hwEta(); if (abs_eta < 0) { abs_eta += (1 << (etaSignShift_ - absEtaShift_)); @@ -212,22 +212,22 @@ void l1t::MuonRawDigiTranslator::generatePackedDataWords(const Muon& mu, (mu.hwPhi() & phiMask_) << phiShift_; } else if ((fedID == 1402 && fwID == 0x6000001) || (fedID == 1404 && fwID < 0x1130)) { // This allows us to unpack data taken in the November 2020 MWGR. - generatePackedDataWordsRun3( + generatePackedMuonDataWordsRun3( mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, true); } else { - generatePackedDataWordsRun3( + generatePackedMuonDataWordsRun3( mu, abs_eta, abs_eta_at_vtx, raw_data_spare, raw_data_00_31, raw_data_32_63, muInBx, false); } } -void l1t::MuonRawDigiTranslator::generatePackedDataWordsRun3(const Muon& mu, - const int abs_eta, - const int abs_eta_at_vtx, - uint32_t& raw_data_spare, - uint32_t& raw_data_00_31, - uint32_t& raw_data_32_63, - const int muInBx, - const bool wasSpecialMWGR /*= false*/) { +void l1t::MuonRawDigiTranslator::generatePackedMuonDataWordsRun3(const Muon& mu, + const int abs_eta, + const int abs_eta_at_vtx, + uint32_t& raw_data_spare, + uint32_t& raw_data_00_31, + uint32_t& raw_data_32_63, + const int muInBx, + const bool wasSpecialMWGR /*= false*/) { int absEtaShiftRun3{0}, etaSignShiftRun3{0}; if (muInBx == 1) { absEtaShiftRun3 = absEtaMu1Shift_; @@ -259,10 +259,25 @@ void l1t::MuonRawDigiTranslator::generate64bitDataWord( uint32_t lsw; uint32_t msw; - generatePackedDataWords(mu, raw_data_spare, lsw, msw, fedId, fwId, muInBx); + generatePackedMuonDataWords(mu, raw_data_spare, lsw, msw, fedId, fwId, muInBx); dataword = (((uint64_t)msw) << 32) + lsw; } +std::array l1t::MuonRawDigiTranslator::getPackedShowerDataWords(const MuonShower& shower, + const int fedId, + const unsigned int fwId) { + std::array res{}; + if (fedId == 1402 && fwId < 0x7000000) { + return res; + } else { + res.at(0) = shower.isOneNominalInTime() ? (1 << showerShift_) : 0; + res.at(1) = shower.isOneNominalOutOfTime() ? (1 << showerShift_) : 0; + res.at(2) = shower.isTwoLooseInTime() ? (1 << showerShift_) : 0; + res.at(3) = shower.isTwoLooseOutOfTime() ? (1 << showerShift_) : 0; + } + return res; +} + int l1t::MuonRawDigiTranslator::calcHwEta(const uint32_t& raw, const unsigned absEtaShift, const unsigned etaSignShift) {