Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:12:30

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