diff --git a/DQM/L1TMonitor/src/L1TStage2Shower.cc b/DQM/L1TMonitor/src/L1TStage2Shower.cc index 94fc93e959377..505bdef9fa7a6 100644 --- a/DQM/L1TMonitor/src/L1TStage2Shower.cc +++ b/DQM/L1TMonitor/src/L1TStage2Shower.cc @@ -166,8 +166,8 @@ void L1TStage2Shower::analyze(const edm::Event& e, const edm::EventSetup& c) { if (not Shower.isValid()) continue; if (Shower.isOneNominalInTime() or Shower.isTwoLooseInTime() or Shower.isOneTightInTime()) { - int endcap = Shower.endcap(); - int sector = Shower.sector(); + int endcap = Shower.trackFinderType() == l1t::tftype::emtf_pos ? 1 : -1; + int sector = Shower.processor() + 1; if (Shower.isOneTightInTime()) emtfShowerTypeOccupancy->Fill(sector, (endcap == 1) ? 7.5 : 0.5); if (Shower.isTwoLooseInTime()) diff --git a/DataFormats/L1TMuon/interface/RegionalMuonShower.h b/DataFormats/L1TMuon/interface/RegionalMuonShower.h index 230dc49d12664..0e02146c8ae22 100644 --- a/DataFormats/L1TMuon/interface/RegionalMuonShower.h +++ b/DataFormats/L1TMuon/interface/RegionalMuonShower.h @@ -5,6 +5,8 @@ #include "DataFormats/L1Trigger/interface/BXVector.h" #include "DataFormats/L1Trigger/interface/L1TObjComparison.h" +#include "RegionalMuonCandFwd.h" // For tftype. + namespace l1t { class RegionalMuonShower; @@ -31,9 +33,8 @@ namespace l1t { void setTwoLooseOutOfTime(const bool bit) { isTwoLooseOutOfTime_ = bit; } void setTwoLooseInTime(const bool bit) { isTwoLooseInTime_ = bit; } - void setEndcap(const int endcap) { endcap_ = endcap; } - void setSector(const unsigned sector) { sector_ = sector; } - void setLink(const int link) { link_ = link; }; + /// Set the processor ID, track-finder type. From these two, the link is set + void setTFIdentifiers(int processor, tftype trackFinder); bool isValid() const; bool isOneNominalInTime() const { return isOneNominalInTime_; } @@ -43,10 +44,12 @@ namespace l1t { bool isTwoLooseInTime() const { return isTwoLooseInTime_; } bool isTwoLooseOutOfTime() const { return isTwoLooseOutOfTime_; } - int endcap() const { return endcap_; } - int sector() const { return sector_; } /// Get link on which the MicroGMT receives the candidate - int link() const { return link_; } + const int link() const { return link_; }; + /// Get processor ID on which the candidate was found (0..5 for OMTF/EMTF; 0..11 for BMTF) + const int processor() const { return processor_; }; + /// Get track-finder which found the muon (bmtf, emtf_pos/emtf_neg or omtf_pos/omtf_neg) + const tftype trackFinderType() const { return trackFinder_; }; bool operator==(const l1t::RegionalMuonShower& rhs) const; inline bool operator!=(const l1t::RegionalMuonShower& rhs) const { return !(operator==(rhs)); }; @@ -60,9 +63,9 @@ namespace l1t { bool isOneTightOutOfTime_; bool isTwoLooseInTime_; bool isTwoLooseOutOfTime_; - int endcap_; // +/-1. For ME+ and ME-. - unsigned sector_; // 1 - 6. int link_; + int processor_; + tftype trackFinder_; }; } // namespace l1t diff --git a/DataFormats/L1TMuon/src/RegionalMuonShower.cc b/DataFormats/L1TMuon/src/RegionalMuonShower.cc index ce73da8584331..ba4c68832686b 100644 --- a/DataFormats/L1TMuon/src/RegionalMuonShower.cc +++ b/DataFormats/L1TMuon/src/RegionalMuonShower.cc @@ -12,12 +12,33 @@ l1t::RegionalMuonShower::RegionalMuonShower(bool oneNominalInTime, isOneTightOutOfTime_(oneTightOutOfTime), isTwoLooseInTime_(twoLooseInTime), isTwoLooseOutOfTime_(twoLooseOutOfTime), - endcap_(0), - sector_(0), - link_(0) {} + link_(0), + processor_(0) {} l1t::RegionalMuonShower::~RegionalMuonShower() {} +void l1t::RegionalMuonShower::setTFIdentifiers(int processor, tftype trackFinder) { + trackFinder_ = trackFinder; + processor_ = processor; + + switch (trackFinder_) { + case tftype::emtf_pos: + link_ = processor_ + 36; // range 36...41 + break; + case tftype::omtf_pos: + link_ = processor_ + 42; // range 42...47 + break; + case tftype::bmtf: + link_ = processor_ + 48; // range 48...59 + break; + case tftype::omtf_neg: + link_ = processor_ + 60; // range 60...65 + break; + case tftype::emtf_neg: + link_ = processor_ + 66; // range 66...71 + } +} + bool l1t::RegionalMuonShower::isValid() const { return (isOneNominalInTime_ or isTwoLooseInTime_ or isOneTightInTime_); } diff --git a/DataFormats/L1TMuon/src/classes_def.xml b/DataFormats/L1TMuon/src/classes_def.xml index d045b4388ab55..07cb26f030624 100644 --- a/DataFormats/L1TMuon/src/classes_def.xml +++ b/DataFormats/L1TMuon/src/classes_def.xml @@ -13,7 +13,8 @@ - + + diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/CommonTokens.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/CommonTokens.h index 5e10377235b2a..a78e7323ad3d3 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/CommonTokens.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/CommonTokens.h @@ -6,6 +6,7 @@ #include "DataFormats/L1Trigger/interface/Jet.h" #include "DataFormats/L1Trigger/interface/Tau.h" #include "DataFormats/L1Trigger/interface/Muon.h" +#include "DataFormats/L1Trigger/interface/MuonShower.h" #include "FWCore/Utilities/interface/EDGetToken.h" #include "EventFilter/L1TRawToDigi/interface/PackerTokens.h" @@ -19,6 +20,7 @@ namespace l1t { inline const edm::EDGetTokenT& getJetToken() const { return jetToken_; }; inline const edm::EDGetTokenT& getTauToken() const { return tauToken_; }; inline const edm::EDGetTokenT& getMuonToken() const { return muonToken_; }; + inline const edm::EDGetTokenT& getMuonShowerToken() const { return muonShowerToken_; }; protected: edm::EDGetTokenT egammaToken_; @@ -26,6 +28,7 @@ namespace l1t { edm::EDGetTokenT jetToken_; edm::EDGetTokenT tauToken_; edm::EDGetTokenT muonToken_; + edm::EDGetTokenT muonShowerToken_; }; } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.cc index 6ba0a8ebcb1d9..8f998e86820a7 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.cc @@ -11,7 +11,7 @@ namespace l1t { event_.put(std::move(regionalMuonCandsOMTF_), "OMTF"); event_.put(std::move(regionalMuonCandsEMTF_), "EMTF"); event_.put(std::move(muons_[0]), "Muon"); - for (int i = 1; i < 6; ++i) { + for (size_t i = 1; i < NUM_OUTPUT_COPIES; ++i) { event_.put(std::move(muons_[i]), "MuonCopy" + std::to_string(i)); } event_.put(std::move(imdMuonsBMTF_), "imdMuonsBMTF"); @@ -19,6 +19,12 @@ namespace l1t { event_.put(std::move(imdMuonsEMTFPos_), "imdMuonsEMTFPos"); event_.put(std::move(imdMuonsOMTFNeg_), "imdMuonsOMTFNeg"); event_.put(std::move(imdMuonsOMTFPos_), "imdMuonsOMTFPos"); + + event_.put(std::move(regionalMuonShowersEMTF_), "EMTF"); + event_.put(std::move(muonShowers_[0]), "MuonShower"); + for (size_t i = 1; i < NUM_OUTPUT_COPIES; ++i) { + event_.put(std::move(muonShowers_[i]), "MuonShowerCopy" + std::to_string(i)); + } } } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.h index 281b2ba92a2a8..a02b15d107cc7 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTCollections.h @@ -4,6 +4,9 @@ #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" #include "DataFormats/L1Trigger/interface/Muon.h" +#include "DataFormats/L1TMuon/interface/RegionalMuonShower.h" +#include "DataFormats/L1Trigger/interface/MuonShower.h" + #include "L1TObjectCollections.h" #include @@ -27,10 +30,16 @@ namespace l1t { imdMuonsEMTFNeg_(std::make_unique(0, oFirstBx, oLastBx)), imdMuonsEMTFPos_(std::make_unique(0, oFirstBx, oLastBx)), imdMuonsOMTFNeg_(std::make_unique(0, oFirstBx, oLastBx)), - imdMuonsOMTFPos_(std::make_unique(0, oFirstBx, oLastBx)) { + imdMuonsOMTFPos_(std::make_unique(0, oFirstBx, oLastBx)), + + regionalMuonShowersEMTF_(std::make_unique(0, iFirstBx, iLastBx)), + muonShowers_() { std::generate(muons_.begin(), muons_.end(), [&oFirstBx, &oLastBx] { return std::make_unique(0, oFirstBx, oLastBx); }); + std::generate(muonShowers_.begin(), muonShowers_.end(), [&oFirstBx, &oLastBx] { + return std::make_unique(0, oFirstBx, oLastBx); + }); }; ~GMTCollections() override; @@ -45,6 +54,13 @@ namespace l1t { inline MuonBxCollection* getImdMuonsOMTFNeg() { return imdMuonsOMTFNeg_.get(); }; inline MuonBxCollection* getImdMuonsOMTFPos() { return imdMuonsOMTFPos_.get(); }; + inline RegionalMuonShowerBxCollection* getRegionalMuonShowersEMTF() { return regionalMuonShowersEMTF_.get(); }; + inline MuonShowerBxCollection* getMuonShowers(const unsigned int copy) override { + return muonShowers_[copy].get(); + }; + + static constexpr size_t NUM_OUTPUT_COPIES{6}; + private: std::unique_ptr regionalMuonCandsBMTF_; std::unique_ptr regionalMuonCandsOMTF_; @@ -55,6 +71,9 @@ namespace l1t { std::unique_ptr imdMuonsEMTFPos_; std::unique_ptr imdMuonsOMTFNeg_; std::unique_ptr imdMuonsOMTFPos_; + + std::unique_ptr regionalMuonShowersEMTF_; + std::array, 6> muonShowers_; }; } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTSetup.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTSetup.cc index c4508e7763388..c0846fcddc101 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTSetup.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTSetup.cc @@ -5,11 +5,11 @@ #include "EventFilter/L1TRawToDigi/plugins/PackingSetupFactory.h" #include "EventFilter/L1TRawToDigi/plugins/UnpackerFactory.h" -#include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h" #include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.h" +#include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h" #include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.h" -#include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/IntermediateMuonUnpacker.h" #include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonUnpacker.h" +#include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/IntermediateMuonUnpacker.h" #include "GMTSetup.h" @@ -36,6 +36,8 @@ namespace l1t { ->setComment("uGMT intermediate muon from neg. OMTF side after first sorting stage"); desc.addOptional("ImdInputLabelOMTFPos") ->setComment("uGMT intermediate muon from pos. OMTF side after first sorting stage"); + desc.addOptional("ShowerInputLabel")->setComment("for Run3"); + desc.addOptional("EMTFShowerInputLabel")->setComment("for Run3"); } PackerMap GMTSetup::getPackers(int fed, unsigned int fw) { @@ -43,6 +45,9 @@ namespace l1t { if (fed == 1402) { auto gmt_in_packer = static_pointer_cast( PackerFactory::get()->make("stage2::RegionalMuonGMTPacker")); + if (fw >= 0x7000000) { + gmt_in_packer->setUseEmtfShowers(); + } if (fw >= 0x6010000) { gmt_in_packer->setUseEmtfDisplacementInfo(); } @@ -68,7 +73,7 @@ namespace l1t { prod.produces("OMTF"); prod.produces("EMTF"); prod.produces("Muon"); - for (int i = 1; i < 6; ++i) { + for (size_t i = 1; i < GMTCollections::NUM_OUTPUT_COPIES; ++i) { prod.produces("MuonCopy" + std::to_string(i)); } prod.produces("imdMuonsBMTF"); @@ -76,6 +81,12 @@ namespace l1t { prod.produces("imdMuonsEMTFPos"); prod.produces("imdMuonsOMTFNeg"); prod.produces("imdMuonsOMTFPos"); + + prod.produces("EMTF"); + prod.produces("MuonShower"); + for (size_t i = 1; i < GMTCollections::NUM_OUTPUT_COPIES; ++i) { + prod.produces("MuonShowerCopy" + std::to_string(i)); + } } std::unique_ptr GMTSetup::getCollections(edm::Event& e) { @@ -89,6 +100,9 @@ namespace l1t { // input muons on links 36-71 auto gmt_in_unp = static_pointer_cast( UnpackerFactory::get()->make("stage2::RegionalMuonGMTUnpacker")); + if (fw >= 0x7000000) { + gmt_in_unp->setUseEmtfShowers(); + } if (fw >= 0x6010000) { gmt_in_unp->setUseEmtfDisplacementInfo(); } diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.cc index 39269759ccd0b..2c992a9742c8a 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.cc @@ -26,6 +26,12 @@ namespace l1t { imdMuonTokenEMTFPos_ = cc.consumes(imdEmtfPosTag); imdMuonTokenOMTFNeg_ = cc.consumes(imdOmtfNegTag); imdMuonTokenOMTFPos_ = cc.consumes(imdOmtfPosTag); + + auto emtfShowerTag = cfg.getParameter("EMTFShowerInputLabel"); + auto showerTag = cfg.getParameter("ShowerInputLabel"); + + regionalMuonShowerTokenEMTF_ = cc.consumes(emtfShowerTag); + muonShowerToken_ = cc.consumes(showerTag); } } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.h index 9838e11fed804..6089529a9d47d 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/GMTTokens.h @@ -2,6 +2,7 @@ #define GMTTokens_h #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" +#include "DataFormats/L1TMuon/interface/RegionalMuonShower.h" #include "DataFormats/L1Trigger/interface/Muon.h" #include "CommonTokens.h" @@ -27,6 +28,10 @@ namespace l1t { inline const edm::EDGetTokenT& getImdMuonTokenOMTFNeg() const { return imdMuonTokenOMTFNeg_; }; inline const edm::EDGetTokenT& getImdMuonTokenOMTFPos() const { return imdMuonTokenOMTFPos_; }; + inline const edm::EDGetTokenT& getRegionalMuonShowerTokenEMTF() const { + return regionalMuonShowerTokenEMTF_; + }; + private: edm::EDGetTokenT regionalMuonCandTokenBMTF_; edm::EDGetTokenT regionalMuonCandTokenOMTF_; @@ -36,6 +41,8 @@ namespace l1t { edm::EDGetTokenT imdMuonTokenEMTFPos_; edm::EDGetTokenT imdMuonTokenOMTFNeg_; edm::EDGetTokenT imdMuonTokenOMTFPos_; + + edm::EDGetTokenT regionalMuonShowerTokenEMTF_; }; } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/L1TObjectCollections.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/L1TObjectCollections.h index f543f9ce0ff98..1650face93738 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/L1TObjectCollections.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/L1TObjectCollections.h @@ -6,6 +6,7 @@ #include "DataFormats/L1Trigger/interface/Jet.h" #include "DataFormats/L1Trigger/interface/Tau.h" #include "DataFormats/L1Trigger/interface/Muon.h" +#include "DataFormats/L1Trigger/interface/MuonShower.h" #include "DataFormats/EcalDigi/interface/EcalDigiCollections.h" @@ -19,6 +20,7 @@ namespace l1t { ~L1TObjectCollections() override; virtual MuonBxCollection* getMuons(const unsigned int copy) { return nullptr; } + virtual MuonShowerBxCollection* getMuonShowers(const unsigned int copy) { return nullptr; } virtual EGammaBxCollection* getEGammas(const unsigned int copy) { return nullptr; } //= 0; virtual EtSumBxCollection* getEtSums(const unsigned int copy) { return nullptr; } virtual JetBxCollection* getJets(const unsigned int copy) { return nullptr; } diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/MuonPacker.cc index f2d62ae8f8470..25c949d9b4c9f 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) { + objMap[bx] = GMTObjects(); + 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)}; - 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 + 1; ++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_; + 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}; + auto mu{objMap.at(bx).mus.begin()}; // Need to get the first muon of that bx from the object map + 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/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.cc index 36301c3037568..281edd581d460 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.cc @@ -1,3 +1,4 @@ +#include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/Framework/interface/Event.h" #include "EventFilter/L1TRawToDigi/plugins/PackerFactory.h" @@ -8,62 +9,121 @@ namespace l1t { namespace stage2 { Blocks RegionalMuonGMTPacker::pack(const edm::Event& event, const PackerTokens* toks) { + GMTObjectMap bmtfObjMap; + GMTObjectMap omtfObjMap; + GMTObjectMap emtfObjMap; auto bmtfToken = static_cast(toks)->getRegionalMuonCandTokenBMTF(); auto omtfToken = static_cast(toks)->getRegionalMuonCandTokenOMTF(); auto emtfToken = static_cast(toks)->getRegionalMuonCandTokenEMTF(); + // First we put the muons in our object map. + std::pair bmtfMuonBx = getMuons(bmtfObjMap, event, bmtfToken); + std::pair omtfMuonBx = getMuons(omtfObjMap, event, omtfToken); + std::pair emtfMuonBx = getMuons(emtfObjMap, event, emtfToken); + + // Then the showers (We don't expect to have shower data from BMTF and OMTF -- at the moment, at least) + std::pair emtfMuonShowerBx{0, 0}; + if (useEmtfShowers_) { + auto emtfShowerToken = static_cast(toks)->getRegionalMuonShowerTokenEMTF(); + emtfMuonShowerBx = getMuonShowers(emtfObjMap, event, emtfShowerToken); + } + Blocks blocks; - // pack the muons for each TF in blocks - packTF(event, bmtfToken, blocks); - packTF(event, omtfToken, blocks); - packTF(event, emtfToken, blocks); + // Pack the muons and showers for each TF in blocks + packTF(bmtfObjMap, bmtfMuonBx.first, bmtfMuonBx.second, 0, 0, blocks); + packTF(omtfObjMap, omtfMuonBx.first, omtfMuonBx.second, 0, 0, blocks); + packTF(emtfObjMap, emtfMuonBx.first, emtfMuonBx.second, emtfMuonShowerBx.first, emtfMuonShowerBx.second, blocks); return blocks; } - void RegionalMuonGMTPacker::packTF(const edm::Event& event, - const edm::EDGetTokenT& tfToken, - Blocks& blocks) { + std::pair RegionalMuonGMTPacker::getMuonShowers( + GMTObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& tfShowerToken) { + edm::Handle muonShowers; + event.getByToken(tfShowerToken, muonShowers); + for (int bx = muonShowers->getFirstBX(); bx <= muonShowers->getLastBX(); ++bx) { + for (auto muShower = muonShowers->begin(bx); muShower != muonShowers->end(bx); ++muShower) { + objMap[bx][muShower->link()].shower = *muShower; + } + } + return std::make_pair(muonShowers->getFirstBX(), muonShowers->getLastBX()); + } + + std::pair RegionalMuonGMTPacker::getMuons(GMTObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& tfToken) { edm::Handle muons; event.getByToken(tfToken, muons); + for (int bx = muons->getFirstBX(); bx <= muons->getLastBX(); ++bx) { + for (auto mu = muons->begin(bx); mu != muons->end(bx); ++mu) { + objMap[bx][mu->link()].mus.push_back(*mu); + } + } + return std::make_pair(muons->getFirstBX(), muons->getLastBX()); + } - constexpr unsigned wordsPerBx = 6; // number of 32 bit words per BX + void RegionalMuonGMTPacker::packTF(const GMTObjectMap& objMap, + const int firstMuonBx, + const int lastMuonBx, + const int firstMuonShowerBx, + const int lastMuonShowerBx, + Blocks& blocks) { + const auto firstBx{std::min(firstMuonShowerBx, firstMuonBx)}; + const auto lastBx{std::max(lastMuonShowerBx, lastMuonBx)}; + const auto nBx{lastBx - firstBx + 1}; PayloadMap payloadMap; - const auto nBx = muons->getLastBX() - muons->getFirstBX() + 1; unsigned bxCtr = 0; - for (int i = muons->getFirstBX(); i <= muons->getLastBX(); ++i, ++bxCtr) { - for (auto mu = muons->begin(i); mu != muons->end(i); ++mu) { - const auto linkTimes2 = mu->link() * 2; - - // If the map key is new reserve the payload size. - if (payloadMap.count(linkTimes2) == 0) { - payloadMap[linkTimes2].reserve(wordsPerBx * nBx); - // If there was no muon on the link of this muon in previous - // BX the payload up to this BX must be filled with zeros. - if (bxCtr > 0) { - while (payloadMap[linkTimes2].size() < bxCtr * wordsPerBx) { - payloadMap[linkTimes2].push_back(0); + for (int bx{firstBx}; bx < lastBx + 1; ++bx, ++bxCtr) { + if (objMap.count(bx) > 0) { + for (const auto& linkMap : objMap.at(bx)) { + const auto linkTimes2{linkMap.first * 2}; + const auto gmtObjects{linkMap.second}; + + // If the payload map key is new reserve the payload size. + if (payloadMap.count(linkTimes2) == 0) { + payloadMap[linkTimes2].reserve(wordsPerBx_ * nBx); + // If there was no muon on the link of this muon in previous + // BX the payload up to this BX must be filled with zeros. + if (bxCtr > 0) { + while (payloadMap[linkTimes2].size() < bxCtr * wordsPerBx_) { + payloadMap[linkTimes2].push_back(0); + } } } - } - // Fill the muon in the payload for this link. - uint32_t msw = 0; - uint32_t lsw = 0; + if (gmtObjects.mus.size() > 3) { + edm::LogError("L1T") << "Muon collection for link " << linkMap.first << " has " << gmtObjects.mus.size() + << " entries, but 3 is the maximum!"; + } - RegionalMuonRawDigiTranslator::generatePackedDataWords(*mu, lsw, msw, isKbmtf_, useEmtfDisplacementInfo_); + std::array buf{}; // Making sure contents of buf are initialised to 0. + size_t frameIdx{0}; + for (const auto& mu : gmtObjects.mus) { + // Fill the muon in the payload for this link. + uint32_t msw{0}; + uint32_t lsw{0}; - payloadMap[linkTimes2].push_back(lsw); - payloadMap[linkTimes2].push_back(msw); - } + RegionalMuonRawDigiTranslator::generatePackedDataWords(mu, lsw, msw, isKbmtf_, useEmtfDisplacementInfo_); - // padding to 3 muons per block id (link) per BX - // This can be empty muons as well. + buf.at(frameIdx++) = lsw; + buf.at(frameIdx++) = msw; + } + // Add shower bits to the payload buffer. + RegionalMuonRawDigiTranslator::generatePackedShowerPayload(gmtObjects.shower, buf, useEmtfShowers_); + + payloadMap[linkTimes2].insert( + payloadMap[linkTimes2].end(), std::move_iterator(buf.begin()), std::move_iterator(buf.end())); + } + } + // We now loop over all channels in the payload map and make sure that they are filled up to the current BX + // If they are not, we fill them with zeros for (auto& kv : payloadMap) { - while (kv.second.size() < (bxCtr + 1) * wordsPerBx) { + while (kv.second.size() < (bxCtr + 1) * wordsPerBx_) { kv.second.push_back(0); } } @@ -74,6 +134,7 @@ namespace l1t { blocks.push_back(Block(kv.first, kv.second)); } } + } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.h index e3feb1bce562b..fa356b1812256 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTPacker.h @@ -6,6 +6,7 @@ #include "EventFilter/L1TRawToDigi/interface/PackerTokens.h" #include "EventFilter/L1TRawToDigi/interface/Block.h" #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" +#include "DataFormats/L1TMuon/interface/RegionalMuonShower.h" #include "FWCore/Framework/interface/Event.h" namespace l1t { @@ -15,13 +16,33 @@ namespace l1t { Blocks pack(const edm::Event&, const PackerTokens*) override; void setIsKbmtf() { isKbmtf_ = true; }; void setUseEmtfDisplacementInfo() { useEmtfDisplacementInfo_ = true; }; + void setUseEmtfShowers() { useEmtfShowers_ = true; }; private: + struct GMTObjects { + std::vector mus; + RegionalMuonShower shower; + }; + typedef std::map> GMTObjectMap; // Map of BX --> linkID --> objects typedef std::map> PayloadMap; - void packTF(const edm::Event&, const edm::EDGetTokenT&, Blocks&); + void packTF(const GMTObjectMap& objMap, + int firstMuonBx, + int lastMuonBx, + int firstMuonShowerBx, + int lastMuonShowerBx, + Blocks&); + std::pair getMuons(GMTObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& tfToken); + std::pair getMuonShowers(GMTObjectMap& objMap, + const edm::Event& event, + const edm::EDGetTokenT& tfShowerToken); + + static constexpr size_t wordsPerBx_ = 6; // number of 32 bit words per BX bool isKbmtf_{false}; bool useEmtfDisplacementInfo_{false}; + bool useEmtfShowers_{false}; }; } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.cc b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.cc index 57a603a82294e..7f498ef48abe4 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.cc +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.cc @@ -33,14 +33,19 @@ namespace l1t { // decide which collection to use according to the link ID unsigned int linkId = blockId / 2; int processor; - RegionalMuonCandBxCollection* res; + RegionalMuonCandBxCollection* regionalMuonCollection; + RegionalMuonShowerBxCollection* regionalMuonShowerCollection; tftype trackFinder; if (linkId > 47 && linkId < 60) { - res = static_cast(coll)->getRegionalMuonCandsBMTF(); + regionalMuonCollection = static_cast(coll)->getRegionalMuonCandsBMTF(); + regionalMuonShowerCollection = + new RegionalMuonShowerBxCollection(); // To avoid warning re uninitialised collection trackFinder = tftype::bmtf; processor = linkId - 48; } else if (linkId > 41 && linkId < 66) { - res = static_cast(coll)->getRegionalMuonCandsOMTF(); + regionalMuonCollection = static_cast(coll)->getRegionalMuonCandsOMTF(); + regionalMuonShowerCollection = + new RegionalMuonShowerBxCollection(); // To avoid warning re uninitialised collection if (linkId < 48) { trackFinder = tftype::omtf_pos; processor = linkId - 42; @@ -49,7 +54,8 @@ namespace l1t { processor = linkId - 60; } } else if (linkId > 35 && linkId < 72) { - res = static_cast(coll)->getRegionalMuonCandsEMTF(); + regionalMuonCollection = static_cast(coll)->getRegionalMuonCandsEMTF(); + regionalMuonShowerCollection = static_cast(coll)->getRegionalMuonShowersEMTF(); if (linkId < 42) { trackFinder = tftype::emtf_pos; processor = linkId - 36; @@ -61,7 +67,8 @@ namespace l1t { edm::LogError("L1T") << "No TF muon expected for link " << linkId; return false; } - res->setBXRange(firstBX, lastBX); + regionalMuonCollection->setBXRange(firstBX, lastBX); + regionalMuonShowerCollection->setBXRange(firstBX, lastBX); LogDebug("L1T") << "nBX = " << nBX << " first BX = " << firstBX << " lastBX = " << lastBX; @@ -108,7 +115,13 @@ namespace l1t { << mu.hwPt() << " qual " << mu.hwQual() << " sign " << mu.hwSign() << " sign valid " << mu.hwSignValid() << " unconstrained pT " << mu.hwPtUnconstrained(); - res->push_back(bx, mu); + regionalMuonCollection->push_back(bx, mu); + } + // Fill RegionalMuonShower objects. For this we need to look at all six words together. + RegionalMuonShower muShower; + if (RegionalMuonRawDigiTranslator::fillRegionalMuonShower( + muShower, bxPayload, processor, trackFinder, useEmtfShowers_)) { + regionalMuonShowerCollection->push_back(bx, muShower); } } else { unsigned int nWords = diff --git a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h index f991d1cffdca1..53bf86047dddb 100644 --- a/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h +++ b/EventFilter/L1TRawToDigi/plugins/implementations_stage2/RegionalMuonGMTUnpacker.h @@ -12,6 +12,7 @@ namespace l1t { bool unpack(const Block& block, UnpackerCollections* coll) override; void setIsKbmtf() { isKbmtf_ = true; } void setUseEmtfDisplacementInfo() { useEmtfDisplacementInfo_ = true; } + void setUseEmtfShowers() { useEmtfShowers_ = true; } private: static constexpr unsigned nWords_ = 6; // every link transmits 6 words (3 muons) per bx @@ -19,6 +20,7 @@ namespace l1t { bool isKbmtf_{false}; bool useEmtfDisplacementInfo_{false}; + bool useEmtfShowers_{false}; }; } // namespace stage2 } // namespace l1t diff --git a/EventFilter/L1TRawToDigi/python/gmtStage2Raw_cfi.py b/EventFilter/L1TRawToDigi/python/gmtStage2Raw_cfi.py index eb031df1e82fd..d581e48f957e5 100644 --- a/EventFilter/L1TRawToDigi/python/gmtStage2Raw_cfi.py +++ b/EventFilter/L1TRawToDigi/python/gmtStage2Raw_cfi.py @@ -12,6 +12,8 @@ ImdInputLabelEMTFPos = cms.InputTag("simGmtStage2Digis", "imdMuonsEMTFPos"), ImdInputLabelOMTFNeg = cms.InputTag("simGmtStage2Digis", "imdMuonsOMTFNeg"), ImdInputLabelOMTFPos = cms.InputTag("simGmtStage2Digis", "imdMuonsOMTFPos"), + EMTFShowerInputLabel = cms.InputTag("simEmtfShowers", "EMTF"), + ShowerInputLabel = cms.InputTag("simGmtShowerDigis"), FedId = cms.int32(1402), FWId = cms.uint32(0x3000000), # First used uGMT firmware version lenSlinkHeader = cms.untracked.int32(8), @@ -32,4 +34,4 @@ ### Era: Run3_2021 from Configuration.Eras.Modifier_stage2L1Trigger_2021_cff import stage2L1Trigger_2021 -stage2L1Trigger_2021.toModify(gmtStage2Raw, BMTFInputLabel = cms.InputTag("simKBmtfDigis", "BMTF"), FWId = cms.uint32(0x6010000)) +stage2L1Trigger_2021.toModify(gmtStage2Raw, BMTFInputLabel = cms.InputTag("simKBmtfDigis", "BMTF"), FWId = cms.uint32(0x7000000)) 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/interface/RegionalMuonRawDigiTranslator.h b/L1Trigger/L1TMuon/interface/RegionalMuonRawDigiTranslator.h index 3032b3971a240..5336d34903503 100644 --- a/L1Trigger/L1TMuon/interface/RegionalMuonRawDigiTranslator.h +++ b/L1Trigger/L1TMuon/interface/RegionalMuonRawDigiTranslator.h @@ -2,6 +2,7 @@ #define RegionalMuonRawDigiTranslator_h #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" +#include "DataFormats/L1TMuon/interface/RegionalMuonShower.h" namespace l1t { class RegionalMuonRawDigiTranslator { @@ -15,11 +16,16 @@ namespace l1t { bool useEmtfDisplacementInfo); static void fillRegionalMuonCand( RegionalMuonCand& mu, uint64_t dataword, int proc, tftype tf, bool isKbmtf, bool useEmtfDisplacementInfo); + static bool fillRegionalMuonShower( + RegionalMuonShower& muShower, std::vector bxPayload, int proc, tftype tf, bool useEmtfShowers); static void generatePackedDataWords(const RegionalMuonCand& mu, uint32_t& raw_data_00_31, uint32_t& raw_data_32_63, bool isKbmtf, bool useEmtfDisplacementInfo); + static void generatePackedShowerPayload(const RegionalMuonShower& shower, + std::array& payload, + bool useEmtfShowers); static uint64_t generate64bitDataWord(const RegionalMuonCand& mu, bool isKbmtf, bool useEmtfDisplacementInfo); static int generateRawTrkAddress(const RegionalMuonCand&, bool isKalman); @@ -45,6 +51,15 @@ namespace l1t { static constexpr unsigned emtfPtUnconstrainedShift_ = 20; static constexpr unsigned trackAddressMask_ = 0x1FFFFFFF; static constexpr unsigned trackAddressShift_ = 2; + static constexpr unsigned emtfShowerOneNominalFrame_ = 0; + static constexpr unsigned emtfShowerOneNominalMask_ = 0x3; + static constexpr unsigned emtfShowerOneNominalInTimeShift_ = 18; + static constexpr unsigned emtfShowerOneNominalOutOfTimeShift_ = 19; + static constexpr unsigned emtfShowerTwoLooseFrame_ = 2; + static constexpr unsigned emtfShowerTwoLooseMask_ = 0x3; + static constexpr unsigned emtfShowerTwoLooseInTimeShift_ = 18; + static constexpr unsigned emtfShowerTwoLooseOutOfTimeShift_ = 19; + // relative shifts within track address static constexpr unsigned bmtfTrAddrSegSelMask_ = 0xF; static constexpr unsigned bmtfTrAddrSegSelShift_ = 21; diff --git a/L1Trigger/L1TMuon/python/simDigis_cff.py b/L1Trigger/L1TMuon/python/simDigis_cff.py index 134a832412a95..521660d4717fd 100644 --- a/L1Trigger/L1TMuon/python/simDigis_cff.py +++ b/L1Trigger/L1TMuon/python/simDigis_cff.py @@ -108,7 +108,7 @@ from L1Trigger.L1TMuonBarrel.simKBmtfStubs_cfi import * from L1Trigger.L1TMuonBarrel.simKBmtfDigis_cfi import * from Configuration.Eras.Modifier_phase2_trigger_cff import phase2_trigger -phase2_trigger.toReplaceWith(SimL1TMuonTask, cms.Task(SimL1TMuonCommonTask, simTwinMuxDigis, simBmtfDigis, simKBmtfStubs, simKBmtfDigis, simEmtfDigis, simOmtfDigis, simGmtCaloSumDigis, simGmtStage2Digis)) +phase2_trigger.toReplaceWith(SimL1TMuonTask, cms.Task(SimL1TMuonCommonTask, simTwinMuxDigis, simBmtfDigis, simKBmtfStubs, simKBmtfDigis, simEmtfDigis, simOmtfDigis, simGmtCaloSumDigis, simGmtStage2Digis, simEmtfShowers, simGmtShowerDigis)) ## GEM TPs from L1Trigger.L1TGEM.simGEMDigis_cff import * 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) { diff --git a/L1Trigger/L1TMuon/src/RegionalMuonRawDigiTranslator.cc b/L1Trigger/L1TMuon/src/RegionalMuonRawDigiTranslator.cc index d144a84ca0df5..f5faf6008093d 100644 --- a/L1Trigger/L1TMuon/src/RegionalMuonRawDigiTranslator.cc +++ b/L1Trigger/L1TMuon/src/RegionalMuonRawDigiTranslator.cc @@ -114,6 +114,44 @@ void l1t::RegionalMuonRawDigiTranslator::fillRegionalMuonCand(RegionalMuonCand& useEmtfDisplacementInfo); } +bool l1t::RegionalMuonRawDigiTranslator::fillRegionalMuonShower( + RegionalMuonShower& muShower, std::vector bxPayload, int proc, tftype tf, bool useEmtfShowers) { + if (useEmtfShowers && (tf == emtf_pos || tf == emtf_neg)) { + muShower.setTFIdentifiers(proc, tf); + + muShower.setOneNominalInTime(((bxPayload[emtfShowerOneNominalFrame_] >> emtfShowerOneNominalInTimeShift_) & 1) == + 1); + muShower.setOneNominalOutOfTime( + ((bxPayload[emtfShowerOneNominalFrame_] >> emtfShowerOneNominalOutOfTimeShift_) & 1) == 1); + muShower.setTwoLooseInTime(((bxPayload[emtfShowerTwoLooseFrame_] >> emtfShowerTwoLooseInTimeShift_) & 1) == 1); + muShower.setTwoLooseOutOfTime(((bxPayload[emtfShowerTwoLooseFrame_] >> emtfShowerTwoLooseOutOfTimeShift_) & 1) == + 1); + + return true; + } else { + return false; + } +} + +void l1t::RegionalMuonRawDigiTranslator::generatePackedShowerPayload(const RegionalMuonShower& shower, + std::array& payload, + const bool useEmtfShowers) { + if (!useEmtfShowers) { + return; + } + // First we check whether we're going to overwrite something in the payload. + if (((payload.at(emtfShowerOneNominalFrame_) & emtfShowerOneNominalMask_) != 0) || + ((payload.at(emtfShowerTwoLooseFrame_) & emtfShowerTwoLooseMask_) != 0)) { + edm::LogError("L1T") << "Check constants for RegionalMuonShower fields! It looks like we're in danger of " + "overwriting muon data in the packer!"; + return; + } + payload.at(emtfShowerOneNominalFrame_) |= (shower.isOneNominalInTime() & 1) << emtfShowerOneNominalInTimeShift_ | + (shower.isOneNominalOutOfTime() & 1) << emtfShowerOneNominalOutOfTimeShift_; + payload.at(emtfShowerTwoLooseFrame_) |= (shower.isTwoLooseInTime() & 1) << emtfShowerTwoLooseInTimeShift_ | + (shower.isTwoLooseOutOfTime() & 1) << emtfShowerTwoLooseOutOfTimeShift_; +} + void l1t::RegionalMuonRawDigiTranslator::generatePackedDataWords(const RegionalMuonCand& mu, uint32_t& raw_data_00_31, uint32_t& raw_data_32_63, diff --git a/L1Trigger/L1TMuonEndCap/interface/SectorProcessorShower.h b/L1Trigger/L1TMuonEndCap/interface/SectorProcessorShower.h index f48f93ef154e0..bfe1c00688b34 100644 --- a/L1Trigger/L1TMuonEndCap/interface/SectorProcessorShower.h +++ b/L1Trigger/L1TMuonEndCap/interface/SectorProcessorShower.h @@ -15,6 +15,8 @@ #include "DataFormats/CSCDigi/interface/CSCShowerDigiCollection.h" #include "L1Trigger/L1TMuonEndCap/interface/Common.h" +#include "DataFormats/L1TMuon/interface/RegionalMuonCandFwd.h" + #include class SectorProcessorShower { diff --git a/L1Trigger/L1TMuonEndCap/src/SectorProcessorShower.cc b/L1Trigger/L1TMuonEndCap/src/SectorProcessorShower.cc index f271cfea93549..671310fb30218 100644 --- a/L1Trigger/L1TMuonEndCap/src/SectorProcessorShower.cc +++ b/L1Trigger/L1TMuonEndCap/src/SectorProcessorShower.cc @@ -67,10 +67,8 @@ void SectorProcessorShower::process(const CSCShowerDigiCollection& in_showers, if (accept) { // shower output l1t::RegionalMuonShower out_shower(hasOneNominalInTime, false, hasTwoLooseInTime, false, hasOneTightInTime, false); - // convert [1,2] to [1, -1] - const int endcap(endcap_ == 1 ? 1 : -1); - out_shower.setEndcap(endcap); - out_shower.setSector(sector_); + l1t::tftype tftype = (endcap_ == 1) ? l1t::tftype::emtf_pos : l1t::tftype::emtf_neg; + out_shower.setTFIdentifiers(sector_, tftype); out_showers.push_back(0, out_shower); } }