Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:47

0001 // -*- C++ -*-
0002 //
0003 // Package:    L1TMuonProducer
0004 // Class:      L1TMuonProducer
0005 //
0006 /**\class L1TMuonProducer L1TMuonProducer.cc L1Trigger/L1TMuon/src/L1TMuonProducer.cc
0007 
0008  Description: Takes txt-file input and produces barrel- / overlap- / forward TF muons
0009 
0010  Implementation:
0011      [Notes on implementation]
0012 */
0013 //
0014 // Original Author:  Joschka Philip Lingemann,40 3-B01,+41227671598,
0015 //         Created:  Thu Oct  3 16:31:34 CEST 2013
0016 // $Id$
0017 //
0018 //
0019 
0020 // system include files
0021 #include <memory>
0022 #include <fstream>
0023 
0024 // user include files
0025 #include "FWCore/Framework/interface/EventSetup.h"
0026 #include "FWCore/Framework/interface/ESHandle.h"
0027 #include "FWCore/Framework/interface/Frameworkfwd.h"
0028 #include "FWCore/Framework/interface/stream/EDProducer.h"
0029 
0030 #include "FWCore/Framework/interface/Event.h"
0031 #include "FWCore/Framework/interface/MakerMacros.h"
0032 
0033 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0034 #include "FWCore/Utilities/interface/ESGetToken.h"
0035 
0036 #include "L1Trigger/L1TMuon/interface/MicroGMTConfiguration.h"
0037 #include "L1Trigger/L1TMuon/interface/MicroGMTRankPtQualLUT.h"
0038 #include "L1Trigger/L1TMuon/interface/MicroGMTIsolationUnit.h"
0039 #include "L1Trigger/L1TMuon/interface/MicroGMTCancelOutUnit.h"
0040 #include "L1Trigger/L1TMuon/interface/MicroGMTLUTFactories.h"
0041 #include "L1Trigger/L1TMuon/interface/GMTInternalMuon.h"
0042 
0043 #include "DataFormats/Math/interface/LorentzVector.h"
0044 #include "DataFormats/L1Trigger/interface/Muon.h"
0045 #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h"
0046 
0047 #include "CondFormats/L1TObjects/interface/L1TMuonGlobalParams.h"
0048 #include "CondFormats/DataRecord/interface/L1TMuonGlobalParamsRcd.h"
0049 #include "CondFormats/DataRecord/interface/L1TMuonGlobalParamsO2ORcd.h"
0050 #include "L1Trigger/L1TMuon/interface/L1TMuonGlobalParamsHelper.h"
0051 #include "L1Trigger/L1TMuon/interface/L1TMuonGlobalParams_PUBLIC.h"
0052 
0053 #include "TMath.h"
0054 //
0055 // class declaration
0056 //
0057 using namespace l1t;
0058 
0059 class L1TMuonProducer : public edm::stream::EDProducer<> {
0060 public:
0061   explicit L1TMuonProducer(const edm::ParameterSet&);
0062   ~L1TMuonProducer() override;
0063 
0064   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0065 
0066 private:
0067   void produce(edm::Event&, const edm::EventSetup&) override;
0068 
0069   void beginRun(edm::Run const&, edm::EventSetup const&) override;
0070 
0071   static bool compareMuons(const std::shared_ptr<MicroGMTConfiguration::InterMuon>& mu1,
0072                            const std::shared_ptr<MicroGMTConfiguration::InterMuon>& mu2);
0073 
0074   void sortMuons(MicroGMTConfiguration::InterMuonList&, unsigned) const;
0075 
0076   void calculateRank(MicroGMTConfiguration::InterMuonList& muons) const;
0077 
0078   void splitAndConvertMuons(edm::Handle<MicroGMTConfiguration::InputCollection> const& in,
0079                             MicroGMTConfiguration::InterMuonList& out_pos,
0080                             MicroGMTConfiguration::InterMuonList& out_neg,
0081                             GMTInternalWedges& wedges_pos,
0082                             GMTInternalWedges& wedges_neg,
0083                             int bx) const;
0084 
0085   void convertMuons(edm::Handle<MicroGMTConfiguration::InputCollection> const& in,
0086                     MicroGMTConfiguration::InterMuonList& out,
0087                     GMTInternalWedges& wedges,
0088                     int bx) const;
0089 
0090   int computeMuonIdx(const RegionalMuonCand& mu, int currentLink, int muIdxAuto) const;
0091 
0092   void addMuonsToCollections(MicroGMTConfiguration::InterMuonList& coll,
0093                              MicroGMTConfiguration::InterMuonList& interout,
0094                              std::unique_ptr<MuonBxCollection>& out,
0095                              int bx) const;
0096 
0097   // ----------member data ---------------------------
0098   bool m_autoBxRange;
0099   int m_bxMin;
0100   int m_bxMax;
0101   bool m_autoCancelMode;
0102   std::bitset<72> m_inputsToDisable;
0103   std::bitset<28> m_caloInputsToDisable;
0104   std::bitset<12> m_bmtfInputsToDisable;
0105   std::bitset<12> m_omtfInputsToDisable;
0106   std::bitset<12> m_emtfInputsToDisable;
0107   std::bitset<72> m_maskedInputs;
0108   std::bitset<28> m_maskedCaloInputs;
0109   std::bitset<12> m_maskedBmtfInputs;
0110   std::bitset<12> m_maskedOmtfInputs;
0111   std::bitset<12> m_maskedEmtfInputs;
0112   std::unique_ptr<L1TMuonGlobalParamsHelper> microGMTParamsHelper;
0113   edm::InputTag m_barrelTfInputTag;
0114   edm::InputTag m_overlapTfInputTag;
0115   edm::InputTag m_endcapTfInputTag;
0116   edm::InputTag m_trigTowerTag;
0117   std::shared_ptr<MicroGMTRankPtQualLUT> m_rankPtQualityLUT;
0118   MicroGMTIsolationUnit m_isolationUnit;
0119   MicroGMTCancelOutUnit m_cancelOutUnit;
0120   std::ofstream m_debugOut;
0121   l1t::cancelmode m_bmtfCancelMode;
0122   l1t::cancelmode m_emtfCancelMode;
0123 
0124   edm::EDGetTokenT<MicroGMTConfiguration::InputCollection> m_barrelTfInputToken;
0125   edm::EDGetTokenT<MicroGMTConfiguration::InputCollection> m_overlapTfInputToken;
0126   edm::EDGetTokenT<MicroGMTConfiguration::InputCollection> m_endcapTfInputToken;
0127   edm::EDGetTokenT<MicroGMTConfiguration::CaloInputCollection> m_caloTowerInputToken;
0128   edm::ESGetToken<L1TMuonGlobalParams, L1TMuonGlobalParamsRcd> m_microGMTParamsToken;
0129   edm::ESGetToken<L1TMuonGlobalParams, L1TMuonGlobalParamsO2ORcd> m_o2oProtoToken;
0130 };
0131 
0132 //
0133 // constants, enums and typedefs
0134 //
0135 
0136 //
0137 // static data member definitions
0138 //
0139 
0140 //
0141 // constructors and destructor
0142 //
0143 L1TMuonProducer::L1TMuonProducer(const edm::ParameterSet& iConfig)
0144     : m_debugOut("test/debug/iso_debug.dat"),
0145       m_bmtfCancelMode(cancelmode::tracks),
0146       m_emtfCancelMode(cancelmode::coordinate) {
0147   // edm::InputTag barrelTfInputTag = iConfig.getParameter<edm::InputTag>("barrelTFInput");
0148   // edm::InputTag overlapTfInputTag = iConfig.getParameter<edm::InputTag>("overlapTFInput");
0149   // edm::InputTag forwardTfInputTag = iConfig.getParameter<edm::InputTag>("forwardTFInput");
0150 
0151   m_barrelTfInputTag = iConfig.getParameter<edm::InputTag>("barrelTFInput");
0152   m_overlapTfInputTag = iConfig.getParameter<edm::InputTag>("overlapTFInput");
0153   m_endcapTfInputTag = iConfig.getParameter<edm::InputTag>("forwardTFInput");
0154   m_trigTowerTag = iConfig.getParameter<edm::InputTag>("triggerTowerInput");
0155 
0156   m_autoBxRange = iConfig.getParameter<bool>("autoBxRange");
0157   m_bxMin = iConfig.getParameter<int>("bxMin");
0158   m_bxMax = iConfig.getParameter<int>("bxMax");
0159 
0160   m_autoCancelMode = iConfig.getParameter<bool>("autoCancelMode");
0161   if (!m_autoCancelMode) {
0162     if (iConfig.getParameter<std::string>("bmtfCancelMode").find("kftracks") == 0) {
0163       m_bmtfCancelMode = cancelmode::kftracks;
0164     }
0165     if (iConfig.getParameter<std::string>("emtfCancelMode").find("tracks") == 0) {
0166       m_emtfCancelMode = cancelmode::tracks;
0167     }
0168   }
0169 
0170   m_barrelTfInputToken = consumes<MicroGMTConfiguration::InputCollection>(m_barrelTfInputTag);
0171   m_overlapTfInputToken = consumes<MicroGMTConfiguration::InputCollection>(m_overlapTfInputTag);
0172   m_endcapTfInputToken = consumes<MicroGMTConfiguration::InputCollection>(m_endcapTfInputTag);
0173   m_caloTowerInputToken = consumes<MicroGMTConfiguration::CaloInputCollection>(m_trigTowerTag);
0174   m_microGMTParamsToken = esConsumes<L1TMuonGlobalParams, L1TMuonGlobalParamsRcd, edm::Transition::BeginRun>();
0175   m_o2oProtoToken = esConsumes<L1TMuonGlobalParams, L1TMuonGlobalParamsO2ORcd, edm::Transition::BeginRun>();
0176 
0177   //register your products
0178   produces<MuonBxCollection>();
0179   produces<MuonBxCollection>("imdMuonsBMTF");
0180   produces<MuonBxCollection>("imdMuonsEMTFPos");
0181   produces<MuonBxCollection>("imdMuonsEMTFNeg");
0182   produces<MuonBxCollection>("imdMuonsOMTFPos");
0183   produces<MuonBxCollection>("imdMuonsOMTFNeg");
0184 }
0185 
0186 L1TMuonProducer::~L1TMuonProducer() { m_debugOut.close(); }
0187 
0188 //
0189 // member functions
0190 //
0191 
0192 // ------------ method called to produce the data  ------------
0193 void L1TMuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0194   using namespace edm;
0195   std::unique_ptr<MuonBxCollection> outMuons(new MuonBxCollection());
0196   std::unique_ptr<MuonBxCollection> imdMuonsBMTF(new MuonBxCollection());
0197   std::unique_ptr<MuonBxCollection> imdMuonsEMTFPos(new MuonBxCollection());
0198   std::unique_ptr<MuonBxCollection> imdMuonsEMTFNeg(new MuonBxCollection());
0199   std::unique_ptr<MuonBxCollection> imdMuonsOMTFPos(new MuonBxCollection());
0200   std::unique_ptr<MuonBxCollection> imdMuonsOMTFNeg(new MuonBxCollection());
0201 
0202   Handle<MicroGMTConfiguration::InputCollection> bmtfMuons;
0203   Handle<MicroGMTConfiguration::InputCollection> emtfMuons;
0204   Handle<MicroGMTConfiguration::InputCollection> omtfMuons;
0205   Handle<MicroGMTConfiguration::CaloInputCollection> trigTowers;
0206 
0207   iEvent.getByToken(m_barrelTfInputToken, bmtfMuons);
0208   iEvent.getByToken(m_endcapTfInputToken, emtfMuons);
0209   iEvent.getByToken(m_overlapTfInputToken, omtfMuons);
0210   iEvent.getByToken(m_caloTowerInputToken, trigTowers);
0211 
0212   // find out the BX range from the inputs
0213   // the smallest BX window defines the output BX window
0214   if (m_autoBxRange) {
0215     int bxMin = -1000;
0216     int bxMax = 1000;
0217     if (!(m_caloInputsToDisable.all() || m_maskedCaloInputs.all())) {
0218       bxMin = std::max(bxMin, trigTowers->getFirstBX());
0219       bxMax = std::min(bxMax, trigTowers->getLastBX());
0220     }
0221     if (!(m_bmtfInputsToDisable.all() || m_maskedBmtfInputs.all())) {
0222       bxMin = std::max(bxMin, bmtfMuons->getFirstBX());
0223       bxMax = std::min(bxMax, bmtfMuons->getLastBX());
0224     }
0225     if (!(m_omtfInputsToDisable.all() || m_maskedOmtfInputs.all())) {
0226       bxMin = std::max(bxMin, omtfMuons->getFirstBX());
0227       bxMax = std::min(bxMax, omtfMuons->getLastBX());
0228     }
0229     if (!(m_emtfInputsToDisable.all() || m_maskedEmtfInputs.all())) {
0230       bxMin = std::max(bxMin, emtfMuons->getFirstBX());
0231       bxMax = std::min(bxMax, emtfMuons->getLastBX());
0232     }
0233     if (bxMin > 0) {
0234       bxMin = 0;
0235     }
0236     if (bxMax < 0) {
0237       bxMax = 0;
0238     }
0239     if (bxMin > -1000) {
0240       m_bxMin = bxMin;
0241     } else {
0242       m_bxMin = 0;
0243     }
0244     if (bxMax < 1000) {
0245       m_bxMax = bxMax;
0246     } else {
0247       m_bxMax = 0;
0248     }
0249   }
0250 
0251   // set BX range for outputs
0252   outMuons->setBXRange(m_bxMin, m_bxMax);
0253   imdMuonsBMTF->setBXRange(m_bxMin, m_bxMax);
0254   imdMuonsEMTFPos->setBXRange(m_bxMin, m_bxMax);
0255   imdMuonsEMTFNeg->setBXRange(m_bxMin, m_bxMax);
0256   imdMuonsOMTFPos->setBXRange(m_bxMin, m_bxMax);
0257   imdMuonsOMTFNeg->setBXRange(m_bxMin, m_bxMax);
0258 
0259   for (int bx = m_bxMin; bx <= m_bxMax; ++bx) {
0260     m_isolationUnit.setTowerSums(*trigTowers, bx);
0261     MicroGMTConfiguration::InterMuonList internMuonsBmtf;
0262     MicroGMTConfiguration::InterMuonList internMuonsEmtfPos;
0263     MicroGMTConfiguration::InterMuonList internMuonsEmtfNeg;
0264     MicroGMTConfiguration::InterMuonList internMuonsOmtfPos;
0265     MicroGMTConfiguration::InterMuonList internMuonsOmtfNeg;
0266 
0267     // These wedges contain shared pointers to the ones in the InterMuonList
0268     GMTInternalWedges omtfNegWedges;
0269     GMTInternalWedges bmtfWedges;
0270     GMTInternalWedges emtfPosWedges;
0271     GMTInternalWedges emtfNegWedges;
0272     GMTInternalWedges omtfPosWedges;
0273 
0274     // this converts the InputMuon type to the InternalMuon type and splits them into
0275     // positive / negative eta collections necessary as LUTs may differ for pos / neg.
0276     convertMuons(bmtfMuons, internMuonsBmtf, bmtfWedges, bx);
0277     splitAndConvertMuons(emtfMuons, internMuonsEmtfPos, internMuonsEmtfNeg, emtfPosWedges, emtfNegWedges, bx);
0278     splitAndConvertMuons(omtfMuons, internMuonsOmtfPos, internMuonsOmtfNeg, omtfPosWedges, omtfNegWedges, bx);
0279 
0280     // cancel out within the track finders:
0281     m_cancelOutUnit.setCancelOutBits(bmtfWedges, tftype::bmtf, m_bmtfCancelMode);
0282     m_cancelOutUnit.setCancelOutBits(omtfPosWedges, tftype::omtf_pos, cancelmode::coordinate);
0283     m_cancelOutUnit.setCancelOutBits(omtfNegWedges, tftype::omtf_neg, cancelmode::coordinate);
0284     m_cancelOutUnit.setCancelOutBits(emtfPosWedges, tftype::emtf_pos, m_emtfCancelMode);
0285     m_cancelOutUnit.setCancelOutBits(emtfNegWedges, tftype::emtf_neg, m_emtfCancelMode);
0286 
0287     // cancel out between track finder acceptance overlaps:
0288     m_cancelOutUnit.setCancelOutBitsOverlapBarrel(omtfPosWedges, bmtfWedges, cancelmode::coordinate);
0289     m_cancelOutUnit.setCancelOutBitsOverlapBarrel(omtfNegWedges, bmtfWedges, cancelmode::coordinate);
0290     m_cancelOutUnit.setCancelOutBitsOverlapEndcap(omtfPosWedges, emtfPosWedges, cancelmode::coordinate);
0291     m_cancelOutUnit.setCancelOutBitsOverlapEndcap(omtfNegWedges, emtfNegWedges, cancelmode::coordinate);
0292 
0293     m_isolationUnit.extrapolateMuons(internMuonsBmtf);
0294     m_isolationUnit.extrapolateMuons(internMuonsEmtfNeg);
0295     m_isolationUnit.extrapolateMuons(internMuonsEmtfPos);
0296     m_isolationUnit.extrapolateMuons(internMuonsOmtfNeg);
0297     m_isolationUnit.extrapolateMuons(internMuonsOmtfPos);
0298 
0299     // the rank calculated here is used in the sort below
0300     calculateRank(internMuonsBmtf);
0301     calculateRank(internMuonsEmtfNeg);
0302     calculateRank(internMuonsEmtfPos);
0303     calculateRank(internMuonsOmtfNeg);
0304     calculateRank(internMuonsOmtfPos);
0305 
0306     // The sort function both sorts and removes all but best "nSurvivors"
0307     sortMuons(internMuonsBmtf, 8);
0308     sortMuons(internMuonsOmtfPos, 4);
0309     sortMuons(internMuonsOmtfNeg, 4);
0310     sortMuons(internMuonsEmtfPos, 4);
0311     sortMuons(internMuonsEmtfNeg, 4);
0312 
0313     // This combines the 5 streams into one InternalMuon collection for
0314     // the final global sort.
0315     MicroGMTConfiguration::InterMuonList internalMuons;
0316     addMuonsToCollections(internMuonsEmtfPos, internalMuons, imdMuonsEMTFPos, bx);
0317     addMuonsToCollections(internMuonsOmtfPos, internalMuons, imdMuonsOMTFPos, bx);
0318     addMuonsToCollections(internMuonsBmtf, internalMuons, imdMuonsBMTF, bx);
0319     addMuonsToCollections(internMuonsOmtfNeg, internalMuons, imdMuonsOMTFNeg, bx);
0320     addMuonsToCollections(internMuonsEmtfNeg, internalMuons, imdMuonsEMTFNeg, bx);
0321 
0322     // sort internal muons and delete all but best 8
0323     sortMuons(internalMuons, 8);
0324 
0325     m_isolationUnit.isolatePreSummed(internalMuons);
0326     // copy muons to output collection...
0327     for (const auto& mu : internalMuons) {
0328       if (mu->hwPt() > 0) {
0329         math::PtEtaPhiMLorentzVector vec{
0330             (mu->hwPt() - 1) * 0.5, mu->hwEta() * 0.010875, mu->hwGlobalPhi() * 0.010908, 0.0};
0331         int iso = mu->hwAbsIso() + (mu->hwRelIso() << 1);
0332         int outMuQual = MicroGMTConfiguration::setOutputMuonQuality(
0333             mu->hwQual(), mu->trackFinderType(), mu->hwHF(), microGMTParamsHelper->fwVersion());
0334         Muon outMu{vec,
0335                    mu->hwPt(),
0336                    mu->hwEta(),
0337                    mu->hwGlobalPhi(),
0338                    outMuQual,
0339                    mu->hwSign(),
0340                    mu->hwSignValid(),
0341                    iso,
0342                    mu->tfMuonIndex(),
0343                    0,
0344                    true,
0345                    mu->hwIsoSum(),
0346                    mu->hwDPhi(),
0347                    mu->hwDEta(),
0348                    mu->hwRank()};
0349 
0350         // Set coordinates at the vertex
0351         outMu.setHwEtaAtVtx(MicroGMTConfiguration::calcMuonHwEtaExtra(outMu));
0352         outMu.setHwPhiAtVtx(MicroGMTConfiguration::calcMuonHwPhiExtra(outMu));
0353         outMu.setEtaAtVtx(MicroGMTConfiguration::calcMuonEtaExtra(outMu));
0354         outMu.setPhiAtVtx(MicroGMTConfiguration::calcMuonPhiExtra(outMu));
0355 
0356         // Set displacement information
0357         int hwPtUnconstrained{mu->hwPtUnconstrained()};
0358         outMu.setPtUnconstrained(
0359             hwPtUnconstrained == 0
0360                 ? 0
0361                 : (hwPtUnconstrained - 1));  // Don't want negative pT, unconstr. pT has LSB of 1 GeV.
0362         outMu.setHwPtUnconstrained(hwPtUnconstrained);
0363         outMu.setHwDXY(mu->hwDXY());
0364 
0365         if (mu->hwSignValid()) {
0366           outMu.setCharge(1 - 2 * mu->hwSign());
0367         } else {
0368           outMu.setCharge(0);
0369         }
0370         m_debugOut << mu->hwCaloPhi() << " " << mu->hwCaloEta() << std::endl;
0371         outMuons->push_back(bx, outMu);
0372       }
0373     }
0374   }
0375 
0376   iEvent.put(std::move(outMuons));
0377   iEvent.put(std::move(imdMuonsBMTF), "imdMuonsBMTF");
0378   iEvent.put(std::move(imdMuonsEMTFPos), "imdMuonsEMTFPos");
0379   iEvent.put(std::move(imdMuonsEMTFNeg), "imdMuonsEMTFNeg");
0380   iEvent.put(std::move(imdMuonsOMTFPos), "imdMuonsOMTFPos");
0381   iEvent.put(std::move(imdMuonsOMTFNeg), "imdMuonsOMTFNeg");
0382 }
0383 
0384 bool L1TMuonProducer::compareMuons(const std::shared_ptr<MicroGMTConfiguration::InterMuon>& mu1,
0385                                    const std::shared_ptr<MicroGMTConfiguration::InterMuon>& mu2) {
0386   return (mu1->hwWins() >= mu2->hwWins());
0387 }
0388 
0389 void L1TMuonProducer::sortMuons(MicroGMTConfiguration::InterMuonList& muons, unsigned nSurvivors) const {
0390   MicroGMTConfiguration::InterMuonList::iterator mu1;
0391   // reset from previous sort stage
0392   for (mu1 = muons.begin(); mu1 != muons.end(); ++mu1) {
0393     (*mu1)->setHwWins(0);
0394   }
0395 
0396   for (mu1 = muons.begin(); mu1 != muons.end(); ++mu1) {
0397     int mu1CancelBit = (*mu1)->hwCancelBit();
0398     auto mu2 = mu1;
0399     mu2++;
0400     for (; mu2 != muons.end(); ++mu2) {
0401       if (mu1CancelBit != 1 && (*mu2)->hwCancelBit() != 1) {
0402         if ((*mu1)->hwRank() >= (*mu2)->hwRank()) {
0403           (*mu1)->increaseWins();
0404         } else {
0405           (*mu2)->increaseWins();
0406         }
0407       } else if (mu1CancelBit != 1) {
0408         (*mu1)->increaseWins();
0409       } else if ((*mu2)->hwCancelBit() != 1) {
0410         (*mu2)->increaseWins();
0411       }
0412     }
0413   }
0414 
0415   size_t nMuonsBefore = muons.size();
0416   int minWins = nMuonsBefore - nSurvivors;
0417 
0418   // remove all muons that were cancelled or that do not have sufficient rank
0419   // (reduces the container size to nSurvivors)
0420   muons.remove_if([&minWins](auto muon) { return ((muon->hwWins() < minWins) || (muon->hwCancelBit() == 1)); });
0421   muons.sort(L1TMuonProducer::compareMuons);
0422 }
0423 
0424 void L1TMuonProducer::calculateRank(MicroGMTConfiguration::InterMuonList& muons) const {
0425   for (auto& mu1 : muons) {
0426     int rank = m_rankPtQualityLUT->lookup(mu1->hwPt(), mu1->hwQual());
0427     mu1->setHwRank(rank);
0428   }
0429 }
0430 
0431 void L1TMuonProducer::addMuonsToCollections(MicroGMTConfiguration::InterMuonList& coll,
0432                                             MicroGMTConfiguration::InterMuonList& interout,
0433                                             std::unique_ptr<MuonBxCollection>& out,
0434                                             int bx) const {
0435   for (auto& mu : coll) {
0436     interout.push_back(mu);
0437     math::PtEtaPhiMLorentzVector vec{(mu->hwPt() - 1) * 0.5, mu->hwEta() * 0.010875, mu->hwGlobalPhi() * 0.010908, 0.0};
0438     int outMuQual = MicroGMTConfiguration::setOutputMuonQuality(
0439         mu->hwQual(), mu->trackFinderType(), mu->hwHF(), microGMTParamsHelper->fwVersion());
0440     // set tfMuonIndex and iso to 0 like in the FW
0441     Muon outMu{vec,
0442                mu->hwPt(),
0443                mu->hwEta(),
0444                mu->hwGlobalPhi(),
0445                outMuQual,
0446                mu->hwSign(),
0447                mu->hwSignValid(),
0448                0,
0449                0,
0450                0,
0451                true,
0452                0,
0453                mu->hwDPhi(),
0454                mu->hwDEta(),
0455                mu->hwRank()};
0456 
0457     int hwPtUnconstrained{mu->hwPtUnconstrained()};
0458     outMu.setPtUnconstrained(hwPtUnconstrained == 0
0459                                  ? 0
0460                                  : (hwPtUnconstrained - 1));  // Don't want negative pT, unconstr. pT has LSB of 1 GeV.
0461     outMu.setHwPtUnconstrained(hwPtUnconstrained);
0462     outMu.setHwDXY(mu->hwDXY());
0463 
0464     if (mu->hwSignValid()) {
0465       outMu.setCharge(1 - 2 * mu->hwSign());
0466     } else {
0467       outMu.setCharge(0);
0468     }
0469 
0470     out->push_back(bx, outMu);
0471   }
0472 }
0473 
0474 void L1TMuonProducer::splitAndConvertMuons(const edm::Handle<MicroGMTConfiguration::InputCollection>& in,
0475                                            MicroGMTConfiguration::InterMuonList& out_pos,
0476                                            MicroGMTConfiguration::InterMuonList& out_neg,
0477                                            GMTInternalWedges& wedges_pos,
0478                                            GMTInternalWedges& wedges_neg,
0479                                            int bx) const {
0480   // initialize the wedge collections:
0481   for (int i = 0; i < 6; ++i) {
0482     wedges_pos[i] = std::vector<std::shared_ptr<GMTInternalMuon>>();
0483     wedges_pos[i].reserve(3);
0484     wedges_neg[i] = std::vector<std::shared_ptr<GMTInternalMuon>>();
0485     wedges_neg[i].reserve(3);
0486   }
0487   if (bx < in->getFirstBX() || bx > in->getLastBX())
0488     return;
0489   int muIdxAuto = 0;
0490   int currentLink = 0;
0491   for (size_t i = 0; i < in->size(bx); ++i, ++muIdxAuto) {
0492     if (in->at(bx, i).hwPt() > 0) {
0493       int link = in->at(bx, i).link();
0494       if (m_inputsToDisable.test(link) || m_maskedInputs.test(link)) {
0495         continue;  // only process if input link is enabled and not masked
0496       }
0497       if (currentLink != link) {
0498         muIdxAuto = 0;
0499         currentLink = link;
0500       }
0501       int gPhi = MicroGMTConfiguration::calcGlobalPhi(
0502           in->at(bx, i).hwPhi(), in->at(bx, i).trackFinderType(), in->at(bx, i).processor());
0503       int tfMuonIdx{computeMuonIdx(in->at(bx, i), currentLink, muIdxAuto)};
0504       std::shared_ptr<GMTInternalMuon> out = std::make_shared<GMTInternalMuon>(in->at(bx, i), gPhi, tfMuonIdx);
0505       if (in->at(bx, i).hwEta() > 0) {
0506         out_pos.push_back(out);
0507         wedges_pos[in->at(bx, i).processor()].push_back(out);
0508       } else {
0509         out_neg.emplace_back(out);
0510         wedges_neg[in->at(bx, i).processor()].push_back(out);
0511       }
0512     }
0513   }
0514   for (int i = 0; i < 6; ++i) {
0515     if (wedges_pos[i].size() > 3)
0516       edm::LogWarning("Input Mismatch") << " too many inputs per processor for emtf+ / omtf+. Wedge " << i << ": Size "
0517                                         << wedges_pos[i].size() << std::endl;
0518     if (wedges_neg[i].size() > 3)
0519       edm::LogWarning("Input Mismatch") << " too many inputs per processor for emtf- / omtf-. Wedge " << i << ": Size "
0520                                         << wedges_neg[i].size() << std::endl;
0521   }
0522 }
0523 
0524 void L1TMuonProducer::convertMuons(const edm::Handle<MicroGMTConfiguration::InputCollection>& in,
0525                                    MicroGMTConfiguration::InterMuonList& out,
0526                                    GMTInternalWedges& wedges,
0527                                    int bx) const {
0528   // initialize the wedge collection:
0529   for (int i = 0; i < 12; ++i) {
0530     wedges[i] = std::vector<std::shared_ptr<GMTInternalMuon>>();
0531     wedges[i].reserve(3);
0532   }
0533   if (bx < in->getFirstBX() || bx > in->getLastBX()) {
0534     return;
0535   }
0536   int muIdxAuto = 0;
0537   int currentLink = 0;
0538   for (size_t i = 0; i < in->size(bx); ++i, ++muIdxAuto) {
0539     if (in->at(bx, i).hwPt() > 0) {
0540       int link = in->at(bx, i).link();
0541       if (m_inputsToDisable.test(link) || m_maskedInputs.test(link)) {
0542         continue;  // only process if input link is enabled and not masked
0543       }
0544       if (currentLink != link) {
0545         muIdxAuto = 0;
0546         currentLink = link;
0547       }
0548       int gPhi = MicroGMTConfiguration::calcGlobalPhi(
0549           in->at(bx, i).hwPhi(), in->at(bx, i).trackFinderType(), in->at(bx, i).processor());
0550       int tfMuonIdx{computeMuonIdx(in->at(bx, i), currentLink, muIdxAuto)};
0551       std::shared_ptr<GMTInternalMuon> outMu = std::make_shared<GMTInternalMuon>(in->at(bx, i), gPhi, tfMuonIdx);
0552       out.emplace_back(outMu);
0553       wedges[in->at(bx, i).processor()].push_back(outMu);
0554     }
0555   }
0556   for (int i = 0; i < 12; ++i) {
0557     if (wedges[i].size() > 3) {
0558       edm::LogWarning("Input Mismatch") << " too many inputs per processor for barrel. Wedge " << i << ": Size "
0559                                         << wedges[i].size() << std::endl;
0560     }
0561   }
0562 }
0563 
0564 int L1TMuonProducer::computeMuonIdx(const RegionalMuonCand& mu, int currentLink, int muIdxAuto) const {
0565   // If the muon index was set in the data format we should use that. Otherwise we use the value computed from the position in the vector.
0566   if (mu.muIdx() != -1) {
0567     return 3 * (currentLink - 36) + mu.muIdx();
0568   } else {
0569     return 3 * (currentLink - 36) + muIdxAuto;
0570   }
0571 }
0572 
0573 // ------------ method called when starting to processes a run  ------------
0574 void L1TMuonProducer::beginRun(edm::Run const& run, edm::EventSetup const& iSetup) {
0575   edm::ESHandle<L1TMuonGlobalParams> microGMTParamsHandle = iSetup.getHandle(m_microGMTParamsToken);
0576 
0577   std::unique_ptr<L1TMuonGlobalParams_PUBLIC> microGMTParams(
0578       new L1TMuonGlobalParams_PUBLIC(cast_to_L1TMuonGlobalParams_PUBLIC(*microGMTParamsHandle.product())));
0579   if (microGMTParams->pnodes_.empty()) {
0580     edm::ESHandle<L1TMuonGlobalParams> o2oProtoHandle = iSetup.getHandle(m_o2oProtoToken);
0581     microGMTParamsHelper = std::make_unique<L1TMuonGlobalParamsHelper>(*o2oProtoHandle.product());
0582   } else
0583     microGMTParamsHelper =
0584         std::make_unique<L1TMuonGlobalParamsHelper>(cast_to_L1TMuonGlobalParams(*microGMTParams.get()));
0585 
0586   //microGMTParamsHelper->print(std::cout);
0587   m_inputsToDisable = microGMTParamsHelper->inputsToDisable();
0588   edm::LogVerbatim("L1TMuonProducer")
0589       << "uGMT inputsToDisable: " << m_inputsToDisable
0590       << "\n                      EMTF-|OMTF-|   BMTF    |OMTF+|EMTF+|            CALO           |  res  0";
0591   m_caloInputsToDisable = microGMTParamsHelper->caloInputsToDisable();
0592   m_bmtfInputsToDisable = microGMTParamsHelper->bmtfInputsToDisable();
0593   m_omtfInputsToDisable = microGMTParamsHelper->omtfInputsToDisable();
0594   m_emtfInputsToDisable = microGMTParamsHelper->emtfInputsToDisable();
0595   m_maskedInputs = microGMTParamsHelper->maskedInputs();
0596   edm::LogVerbatim("L1TMuonProducer")
0597       << "uGMT maskedInputs:    " << m_maskedInputs
0598       << "\n                      EMTF-|OMTF-|   BMTF    |OMTF+|EMTF+|            CALO           |  res  0";
0599   m_maskedCaloInputs = microGMTParamsHelper->maskedCaloInputs();
0600   m_maskedBmtfInputs = microGMTParamsHelper->maskedBmtfInputs();
0601   m_maskedOmtfInputs = microGMTParamsHelper->maskedOmtfInputs();
0602   m_maskedEmtfInputs = microGMTParamsHelper->maskedEmtfInputs();
0603   m_rankPtQualityLUT =
0604       l1t::MicroGMTRankPtQualLUTFactory::create(microGMTParamsHelper->sortRankLUT(), microGMTParamsHelper->fwVersion());
0605   m_isolationUnit.initialise(microGMTParamsHelper.get());
0606   m_cancelOutUnit.initialise(microGMTParamsHelper.get());
0607 
0608   if (m_autoCancelMode) {
0609     if (microGMTParamsHelper->fwVersion() >= 0x6000000) {
0610       m_bmtfCancelMode = cancelmode::kftracks;
0611     }
0612     // TODO: No decision yet on when to use EMTF track addresses for cancel-out.
0613     // if (microGMTParamsHelper->fwVersion() > 0x5000000) {
0614     //   m_emtfCancelMode = cancelmode::tracks;
0615     // }
0616   }
0617 }
0618 
0619 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0620 void L1TMuonProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0621   //The following says we do not know what parameters are allowed so do no validation
0622   // Please change this to state exactly what you do use, even if it is no parameters
0623   edm::ParameterSetDescription desc;
0624   desc.setUnknown();
0625   descriptions.addDefault(desc);
0626 }
0627 
0628 //define this as a plug-in
0629 DEFINE_FWK_MODULE(L1TMuonProducer);