Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:18:29

0001 /** \class L1TTkMuonFilter
0002  *
0003  * See header file for documentation
0004  *
0005  *
0006  *  \author Martin Grunewald
0007  *  \author Simone Gennai
0008  *  \author Thiago Tomei
0009  *
0010  */
0011 
0012 #include "L1TTkMuonFilter.h"
0013 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0014 
0015 #include "DataFormats/Common/interface/Handle.h"
0016 
0017 #include "DataFormats/Common/interface/Ref.h"
0018 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
0019 #include "DataFormats/HLTReco/interface/TriggerTypeDefs.h"
0020 #include "DataFormats/Math/interface/deltaR.h"
0021 
0022 #include "FWCore/Framework/interface/EventSetup.h"
0023 #include "FWCore/Framework/interface/EventSetupRecord.h"
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 #include "FWCore/Utilities/interface/Exception.h"
0026 
0027 #include <algorithm>
0028 //
0029 // constructors and destructor
0030 //
0031 
0032 namespace {
0033   bool isDupMuon(const l1t::TrackerMuonRef& muon, const std::vector<l1t::TrackerMuonRef>& existing) {
0034     for (const auto& exist : existing) {
0035       //it is our understanding that there is an exact eta phi match
0036       //and we should not be concerned with numerical precision
0037       // DISCUSS: should this use hardware or physics pt?
0038       // For the time being we use hardware pt, because this is just for a duplicate check.
0039       if (reco::deltaR2(muon->hwEta(), muon->hwPhi(), exist->hwEta(), exist->hwPhi()) <= 0) {
0040         return true;
0041       }
0042     }
0043     return false;
0044   }
0045 }  // namespace
0046 
0047 L1TTkMuonFilter::L1TTkMuonFilter(const edm::ParameterSet& iConfig)
0048     : HLTFilter(iConfig),
0049       l1TkMuonTag_(iConfig.getParameter<edm::InputTag>("inputTag")),
0050       tkMuonToken_(consumes(l1TkMuonTag_)) {
0051   min_Pt_ = iConfig.getParameter<double>("MinPt");
0052   min_N_ = iConfig.getParameter<int>("MinN");
0053   min_Eta_ = iConfig.getParameter<double>("MinEta");
0054   max_Eta_ = iConfig.getParameter<double>("MaxEta");
0055   applyQuality_ = iConfig.getParameter<bool>("applyQuality");
0056   applyDuplicateRemoval_ = iConfig.getParameter<bool>("applyDuplicateRemoval");
0057   qualities_ = iConfig.getParameter<std::vector<int>>("qualities");
0058   scalings_ = iConfig.getParameter<edm::ParameterSet>("Scalings");
0059   barrelScalings_ = scalings_.getParameter<std::vector<double>>("barrel");
0060   overlapScalings_ = scalings_.getParameter<std::vector<double>>("overlap");
0061   endcapScalings_ = scalings_.getParameter<std::vector<double>>("endcap");
0062 
0063   std::sort(qualities_.begin(), qualities_.end());
0064 
0065   if (applyQuality_ && qualities_.empty()) {
0066     throw cms::Exception("InvalidConfiguration")
0067         << "If you want to applyQuality the qualities vector should not be empty!";
0068   }
0069 }
0070 
0071 L1TTkMuonFilter::~L1TTkMuonFilter() = default;
0072 
0073 //
0074 // member functions
0075 //
0076 
0077 void L1TTkMuonFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0078   edm::ParameterSetDescription desc;
0079   makeHLTFilterDescription(desc);
0080   desc.add<double>("MinPt", -1.0);
0081   desc.add<double>("MinEta", -5.0);
0082   desc.add<double>("MaxEta", 5.0);
0083   desc.add<int>("MinN", 1);
0084   desc.add<edm::InputTag>("inputTag", edm::InputTag("L1TkMuons"));
0085   desc.add<bool>("applyQuality", false);
0086   desc.add<bool>("applyDuplicateRemoval", true);
0087   desc.add<std::vector<int>>("qualities", {});
0088   edm::ParameterSetDescription descScalings;
0089   descScalings.add<std::vector<double>>("barrel", {0.0, 1.0, 0.0});
0090   descScalings.add<std::vector<double>>("overlap", {0.0, 1.0, 0.0});
0091   descScalings.add<std::vector<double>>("endcap", {0.0, 1.0, 0.0});
0092   desc.add<edm::ParameterSetDescription>("Scalings", descScalings);
0093 
0094   descriptions.add("L1TTkMuonFilter", desc);
0095 }
0096 
0097 // ------------ method called to produce the data  ------------
0098 bool L1TTkMuonFilter::hltFilter(edm::Event& iEvent,
0099                                 const edm::EventSetup& iSetup,
0100                                 trigger::TriggerFilterObjectWithRefs& filterproduct) const {
0101   using namespace std;
0102   using namespace edm;
0103   using namespace reco;
0104   using namespace trigger;
0105 
0106   // All HLT filters must create and fill an HLT filter object,
0107   // recording any reconstructed physics objects satisfying (or not)
0108   // this HLT filter, and place it in the Event.
0109 
0110   // The filter object
0111   if (saveTags()) {
0112     filterproduct.addCollectionTag(l1TkMuonTag_);
0113   }
0114 
0115   // Specific filter code
0116 
0117   // get hold of products from Event
0118   Handle<l1t::TrackerMuonCollection> tkMuons;
0119   iEvent.getByToken(tkMuonToken_, tkMuons);
0120 
0121   //it looks rather slow to get the added muons back out of the filterproduct
0122   //so we just make a vector of passing and then add them all at the end
0123   std::vector<l1t::TrackerMuonRef> passingMuons;
0124   auto atrkmuons(tkMuons->begin());
0125   auto otrkmuons(tkMuons->end());
0126   l1t::TrackerMuonCollection::const_iterator itkMuon;
0127   for (itkMuon = atrkmuons; itkMuon != otrkmuons; itkMuon++) {
0128     double offlinePt = this->TkMuonOfflineEt(itkMuon->phPt(), itkMuon->phEta());
0129 
0130     // The muonDetector() and quality() methods are not available for TrackerMuon
0131     // as they were for TkMuon (TkMuon being the old implementation, at the times
0132     // of the HLT-TDR). So we fall back to the hwQual() method inherited from
0133     // L1Candidate, and compare it with a vector of allowed qualities.
0134     bool passesQual = !applyQuality_ || std::binary_search(qualities_.begin(), qualities_.end(), itkMuon->hwQual());
0135 
0136     if (passesQual && offlinePt >= min_Pt_ && itkMuon->phEta() <= max_Eta_ && itkMuon->phEta() >= min_Eta_) {
0137       l1t::TrackerMuonRef ref(tkMuons, distance(atrkmuons, itkMuon));
0138       if (!applyDuplicateRemoval_ || !isDupMuon(ref, passingMuons)) {
0139         passingMuons.push_back(ref);
0140       }
0141     }
0142   }
0143   for (const auto& muon : passingMuons) {
0144     filterproduct.addObject(trigger::TriggerObjectType::TriggerL1TkMu, muon);
0145   }
0146 
0147   // return with final filter decision
0148   const bool accept(static_cast<int>(passingMuons.size()) >= min_N_);
0149   return accept;
0150 }
0151 
0152 double L1TTkMuonFilter::TkMuonOfflineEt(double Et, double Eta) const {
0153   if (std::abs(Eta) < 0.9)
0154     return (barrelScalings_.at(0) + Et * barrelScalings_.at(1) + Et * Et * barrelScalings_.at(2));
0155   else if (std::abs(Eta) < 1.2)
0156     return (overlapScalings_.at(0) + Et * overlapScalings_.at(1) + Et * Et * overlapScalings_.at(2));
0157   else
0158     return (endcapScalings_.at(0) + Et * endcapScalings_.at(1) + Et * Et * endcapScalings_.at(2));
0159 }