Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-14 02:53:32

0001 /**
0002   \class    pat::PATMuonProducer PATMuonProducer.h "PhysicsTools/PatAlgos/interface/PATMuonProducer.h"
0003   \brief    Produces pat::Muon's
0004 
0005    The PATMuonProducer produces analysis-level pat::Muon's starting from
0006    a collection of objects of reco::Muon.
0007 
0008   \author   Steven Lowette, Roger Wolf
0009   \version  $Id: PATMuonProducer.h,v 1.29 2012/08/22 15:02:52 bellan Exp $
0010 */
0011 
0012 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0013 #include "DataFormats/Common/interface/Association.h"
0014 #include "DataFormats/Common/interface/TriggerResults.h"
0015 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0016 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
0017 #include "DataFormats/Math/interface/deltaPhi.h"
0018 #include "DataFormats/Math/interface/deltaR.h"
0019 #include "DataFormats/MuonReco/interface/Muon.h"
0020 #include "DataFormats/MuonReco/interface/MuonSimInfo.h"
0021 #include "DataFormats/MuonReco/interface/MuonTimeExtra.h"
0022 #include "DataFormats/ParticleFlowCandidate/interface/IsolatedPFCandidate.h"
0023 #include "DataFormats/PatCandidates/interface/Muon.h"
0024 #include "DataFormats/PatCandidates/interface/PFIsolation.h"
0025 #include "DataFormats/PatCandidates/interface/PackedCandidate.h"
0026 #include "DataFormats/PatCandidates/interface/TriggerObjectStandAlone.h"
0027 #include "DataFormats/PatCandidates/interface/UserData.h"
0028 #include "DataFormats/VertexReco/interface/Vertex.h"
0029 #include "FWCore/Framework/interface/Event.h"
0030 #include "FWCore/Framework/interface/stream/EDProducer.h"
0031 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0032 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0033 #include "FWCore/ParameterSet/interface/EmptyGroupDescription.h"
0034 #include "FWCore/ParameterSet/interface/FileInPath.h"
0035 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0036 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0037 #include "FWCore/Utilities/interface/Exception.h"
0038 #include "FWCore/Utilities/interface/transform.h"
0039 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
0040 #include "Geometry/Records/interface/GlobalTrackingGeometryRecord.h"
0041 #include "JetMETCorrections/JetCorrector/interface/JetCorrector.h"
0042 #include "PhysicsTools/PatAlgos/interface/EfficiencyLoader.h"
0043 #include "PhysicsTools/PatAlgos/interface/KinResolutionsLoader.h"
0044 #include "PhysicsTools/PatAlgos/interface/MultiIsolator.h"
0045 #include "PhysicsTools/PatAlgos/interface/MuonMvaEstimator.h"
0046 #include "PhysicsTools/PatAlgos/interface/MuonMvaIDEstimator.h"
0047 #include "PhysicsTools/PatAlgos/interface/PATUserDataHelper.h"
0048 #include "PhysicsTools/PatAlgos/interface/SoftMuonMvaEstimator.h"
0049 #include "PhysicsTools/PatUtils/interface/MiniIsolation.h"
0050 #include "TrackingTools/IPTools/interface/IPTools.h"
0051 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0052 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
0053 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
0054 
0055 namespace pat {
0056 
0057   class PATMuonHeavyObjectCache {
0058   public:
0059     PATMuonHeavyObjectCache(const edm::ParameterSet&);
0060 
0061     pat::MuonMvaEstimator const& muonMvaEstimator() const { return *muonMvaEstimator_; }
0062     pat::MuonMvaEstimator const& muonLowPtMvaEstimator() const { return *muonLowPtMvaEstimator_; }
0063     pat::MuonMvaIDEstimator const& muonMvaIDEstimator() const { return *muonMvaIDEstimator_; }
0064     pat::SoftMuonMvaEstimator const& softMuonMvaEstimator() const { return *softMuonMvaEstimator_; }
0065 
0066   private:
0067     std::unique_ptr<const pat::MuonMvaEstimator> muonLowPtMvaEstimator_;
0068     std::unique_ptr<const pat::MuonMvaEstimator> muonMvaEstimator_;
0069     std::unique_ptr<const pat::MuonMvaIDEstimator> muonMvaIDEstimator_;
0070     std::unique_ptr<const pat::SoftMuonMvaEstimator> softMuonMvaEstimator_;
0071   };
0072 
0073   /// foward declarations
0074   class TrackerIsolationPt;
0075   class CaloIsolationEnergy;
0076 
0077   /// class definition
0078   class PATMuonProducer : public edm::stream::EDProducer<edm::GlobalCache<PATMuonHeavyObjectCache>> {
0079   public:
0080     /// default constructir
0081     explicit PATMuonProducer(const edm::ParameterSet& iConfig, PATMuonHeavyObjectCache const*);
0082     /// default destructur
0083     ~PATMuonProducer() override;
0084 
0085     static std::unique_ptr<PATMuonHeavyObjectCache> initializeGlobalCache(const edm::ParameterSet& iConfig) {
0086       return std::make_unique<PATMuonHeavyObjectCache>(iConfig);
0087     }
0088 
0089     static void globalEndJob(PATMuonHeavyObjectCache*) {}
0090 
0091     /// everything that needs to be done during the event loop
0092     void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
0093     /// description of config file parameters
0094     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0095 
0096   private:
0097     /// typedefs for convenience
0098     typedef edm::RefToBase<reco::Muon> MuonBaseRef;
0099     typedef std::vector<edm::Handle<edm::Association<reco::GenParticleCollection>>> GenAssociations;
0100     typedef std::vector<edm::Handle<edm::ValueMap<IsoDeposit>>> IsoDepositMaps;
0101     typedef std::vector<edm::Handle<edm::ValueMap<double>>> IsolationValueMaps;
0102     typedef std::pair<pat::IsolationKeys, edm::InputTag> IsolationLabel;
0103     typedef std::vector<IsolationLabel> IsolationLabels;
0104 
0105     /// common muon filling, for both the standard and PF2PAT case
0106     void fillMuon(Muon& aMuon,
0107                   const MuonBaseRef& muonRef,
0108                   const reco::CandidateBaseRef& baseRef,
0109                   const GenAssociations& genMatches,
0110                   const IsoDepositMaps& deposits,
0111                   const IsolationValueMaps& isolationValues) const;
0112     /// fill label vector from the contents of the parameter set,
0113     /// for the embedding of isoDeposits or userIsolation values
0114     template <typename T>
0115     void readIsolationLabels(const edm::ParameterSet& iConfig,
0116                              const char* psetName,
0117                              IsolationLabels& labels,
0118                              std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens);
0119 
0120     void setMuonMiniIso(pat::Muon& aMuon, const pat::PackedCandidateCollection* pc);
0121     double getRelMiniIsoPUCorrected(const pat::Muon& muon, double rho, const std::vector<double>& area);
0122 
0123     double puppiCombinedIsolation(const pat::Muon& muon, const pat::PackedCandidateCollection* pc);
0124     bool isNeutralHadron(long pdgid);
0125     bool isChargedHadron(long pdgid);
0126     bool isPhoton(long pdgid);
0127 
0128     // embed various impact parameters with errors
0129     // embed high level selection
0130     void embedHighLevel(pat::Muon& aMuon,
0131                         reco::TrackRef track,
0132                         reco::TransientTrack& tt,
0133                         reco::Vertex& primaryVertex,
0134                         bool primaryVertexIsValid,
0135                         reco::BeamSpot& beamspot,
0136                         bool beamspotIsValid);
0137     double relMiniIsoPUCorrected(const pat::Muon& aMuon, double rho);
0138     std::optional<GlobalPoint> getMuonDirection(const reco::MuonChamberMatch& chamberMatch,
0139                                                 const edm::ESHandle<GlobalTrackingGeometry>& geometry,
0140                                                 const DetId& chamberId);
0141     void fillL1TriggerInfo(pat::Muon& muon,
0142                            edm::Handle<std::vector<pat::TriggerObjectStandAlone>>& triggerObjects,
0143                            const edm::TriggerNames& names,
0144                            const edm::ESHandle<GlobalTrackingGeometry>& geometry);
0145     void fillHltTriggerInfo(pat::Muon& muon,
0146                             edm::Handle<std::vector<pat::TriggerObjectStandAlone>>& triggerObjects,
0147                             const edm::TriggerNames& names,
0148                             const std::vector<std::string>& collection_names);
0149 
0150   private:
0151     /// input source
0152     edm::EDGetTokenT<edm::View<reco::Muon>> muonToken_;
0153 
0154     // for mini-iso calculation
0155     edm::EDGetTokenT<pat::PackedCandidateCollection> pcToken_;
0156     bool computeMiniIso_;
0157     bool computePuppiCombinedIso_;
0158     std::vector<double> effectiveAreaVec_;
0159     std::vector<double> miniIsoParams_;
0160     double relMiniIsoPUCorrected_;
0161 
0162     /// embed the track from best muon measurement (global pflow)
0163     bool embedBestTrack_;
0164     /// embed the track from best muon measurement (muon only)
0165     bool embedTunePBestTrack_;
0166     /// force separate embed of the best track even if already embedded
0167     bool forceEmbedBestTrack_;
0168     /// embed the track from inner tracker into the muon
0169     bool embedTrack_;
0170     /// embed track from muon system into the muon
0171     bool embedStandAloneMuon_;
0172     /// embed track of the combined fit into the muon
0173     bool embedCombinedMuon_;
0174     /// embed muon MET correction info for caloMET into the muon
0175     bool embedCaloMETMuonCorrs_;
0176     /// source of caloMET muon corrections
0177     edm::EDGetTokenT<edm::ValueMap<reco::MuonMETCorrectionData>> caloMETMuonCorrsToken_;
0178     /// embed muon MET correction info for tcMET into the muon
0179     bool embedTcMETMuonCorrs_;
0180     /// source of tcMET muon corrections
0181     edm::EDGetTokenT<edm::ValueMap<reco::MuonMETCorrectionData>> tcMETMuonCorrsToken_;
0182     /// embed track from picky muon fit into the muon
0183     bool embedPickyMuon_;
0184     /// embed track from tpfms muon fit into the muon
0185     bool embedTpfmsMuon_;
0186     /// embed track from DYT muon fit into the muon
0187     bool embedDytMuon_;
0188     /// add combined inverse beta measurement into the muon
0189     bool addInverseBeta_;
0190     /// input tag for reading inverse beta
0191     edm::EDGetTokenT<edm::ValueMap<reco::MuonTimeExtra>> muonTimeExtraToken_;
0192     /// add generator match information
0193     bool addGenMatch_;
0194     /// input tags for generator match information
0195     std::vector<edm::EDGetTokenT<edm::Association<reco::GenParticleCollection>>> genMatchTokens_;
0196     /// embed the gen match information into the muon
0197     bool embedGenMatch_;
0198     /// add resolutions to the muon (this will be data members of th muon even w/o embedding)
0199     bool addResolutions_;
0200     /// helper class to add resolutions to the muon
0201     pat::helper::KinResolutionsLoader resolutionLoader_;
0202     /// switch to use particle flow (PF2PAT) or not
0203     bool useParticleFlow_;
0204     /// input source pfCandidates that will be to be transformed into pat::Muons, when using PF2PAT
0205     edm::EDGetTokenT<reco::PFCandidateCollection> pfMuonToken_;
0206     /// embed pfCandidates into the muon
0207     bool embedPFCandidate_;
0208     /// embed high level selection variables
0209     bool embedHighLevelSelection_;
0210     /// input source of the primary vertex/beamspot
0211     edm::EDGetTokenT<reco::BeamSpot> beamLineToken_;
0212     /// input source of the primary vertex
0213     edm::EDGetTokenT<std::vector<reco::Vertex>> pvToken_;
0214     /// input source for isoDeposits
0215     IsolationLabels isoDepositLabels_;
0216     std::vector<edm::EDGetTokenT<edm::ValueMap<IsoDeposit>>> isoDepositTokens_;
0217     /// input source isolation value maps
0218     IsolationLabels isolationValueLabels_;
0219     std::vector<edm::EDGetTokenT<edm::ValueMap<double>>> isolationValueTokens_;
0220     /// add efficiencies to the muon (this will be data members of th muon even w/o embedding)
0221     bool addEfficiencies_;
0222     /// add user data to the muon (this will be data members of th muon even w/o embedding)
0223     bool useUserData_;
0224     /// add ecal PF energy
0225     bool embedPfEcalEnergy_;
0226     /// add puppi isolation
0227     bool addPuppiIsolation_;
0228     //PUPPI isolation tokens
0229     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons_;
0230     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons_;
0231     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_photons_;
0232     //PUPPINoLeptons isolation tokens
0233     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_charged_hadrons_;
0234     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_neutral_hadrons_;
0235     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_photons_;
0236     /// standard muon selectors
0237     bool computeMuonMVA_;
0238     bool computeMuonIDMVA_;
0239     bool computeSoftMuonMVA_;
0240     bool recomputeBasicSelectors_;
0241     bool mvaUseJec_;
0242     edm::EDGetTokenT<reco::JetTagCollection> mvaBTagCollectionTag_;
0243     edm::EDGetTokenT<reco::JetCorrector> mvaL1Corrector_;
0244     edm::EDGetTokenT<reco::JetCorrector> mvaL1L2L3ResCorrector_;
0245     edm::EDGetTokenT<double> rho_;
0246 
0247     /// --- tools ---
0248     /// helper class to add userdefined isolation values to the muon
0249     pat::helper::MultiIsolator isolator_;
0250     /// isolation value pair for temporary storage before being folded into the muon
0251     pat::helper::MultiIsolator::IsolationValuePairs isolatorTmpStorage_;
0252     /// helper class to add efficiencies to the muon
0253     pat::helper::EfficiencyLoader efficiencyLoader_;
0254     /// helper class to add userData to the muon
0255     pat::PATUserDataHelper<pat::Muon> userDataHelper_;
0256 
0257     /// MC info
0258     edm::EDGetTokenT<edm::ValueMap<reco::MuonSimInfo>> simInfo_;
0259 
0260     /// Trigger
0261     bool addTriggerMatching_;
0262     edm::EDGetTokenT<std::vector<pat::TriggerObjectStandAlone>> triggerObjects_;
0263     edm::EDGetTokenT<edm::TriggerResults> triggerResults_;
0264     std::vector<std::string> hltCollectionFilters_;
0265 
0266     const edm::ESGetToken<GlobalTrackingGeometry, GlobalTrackingGeometryRecord> geometryToken_;
0267     const edm::ESGetToken<TransientTrackBuilder, TransientTrackRecord> transientTrackBuilderToken_;
0268 
0269     const edm::EDPutTokenT<std::vector<Muon>> patMuonPutToken_;
0270   };
0271 
0272 }  // namespace pat
0273 
0274 template <typename T>
0275 void pat::PATMuonProducer::readIsolationLabels(const edm::ParameterSet& iConfig,
0276                                                const char* psetName,
0277                                                pat::PATMuonProducer::IsolationLabels& labels,
0278                                                std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens) {
0279   labels.clear();
0280 
0281   if (iConfig.exists(psetName)) {
0282     edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>(psetName);
0283 
0284     if (depconf.exists("tracker"))
0285       labels.emplace_back(pat::TrackIso, depconf.getParameter<edm::InputTag>("tracker"));
0286     if (depconf.exists("ecal"))
0287       labels.emplace_back(pat::EcalIso, depconf.getParameter<edm::InputTag>("ecal"));
0288     if (depconf.exists("hcal"))
0289       labels.emplace_back(pat::HcalIso, depconf.getParameter<edm::InputTag>("hcal"));
0290     if (depconf.exists("pfAllParticles")) {
0291       labels.emplace_back(pat::PfAllParticleIso, depconf.getParameter<edm::InputTag>("pfAllParticles"));
0292     }
0293     if (depconf.exists("pfChargedHadrons")) {
0294       labels.emplace_back(pat::PfChargedHadronIso, depconf.getParameter<edm::InputTag>("pfChargedHadrons"));
0295     }
0296     if (depconf.exists("pfChargedAll")) {
0297       labels.emplace_back(pat::PfChargedAllIso, depconf.getParameter<edm::InputTag>("pfChargedAll"));
0298     }
0299     if (depconf.exists("pfPUChargedHadrons")) {
0300       labels.emplace_back(pat::PfPUChargedHadronIso, depconf.getParameter<edm::InputTag>("pfPUChargedHadrons"));
0301     }
0302     if (depconf.exists("pfNeutralHadrons")) {
0303       labels.emplace_back(pat::PfNeutralHadronIso, depconf.getParameter<edm::InputTag>("pfNeutralHadrons"));
0304     }
0305     if (depconf.exists("pfPhotons")) {
0306       labels.emplace_back(pat::PfGammaIso, depconf.getParameter<edm::InputTag>("pfPhotons"));
0307     }
0308     if (depconf.exists("user")) {
0309       std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag>>("user");
0310       std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
0311       int key = pat::IsolationKeys::UserBaseIso;
0312       for (; it != ed; ++it, ++key) {
0313         labels.push_back(std::make_pair(pat::IsolationKeys(key), *it));
0314       }
0315       tokens = edm::vector_transform(
0316           labels, [this](IsolationLabel const& label) { return consumes<edm::ValueMap<T>>(label.second); });
0317     }
0318   }
0319   tokens = edm::vector_transform(labels, [this](pat::PATMuonProducer::IsolationLabel const& label) {
0320     return consumes<edm::ValueMap<T>>(label.second);
0321   });
0322 }
0323 
0324 using namespace pat;
0325 using namespace std;
0326 
0327 PATMuonHeavyObjectCache::PATMuonHeavyObjectCache(const edm::ParameterSet& iConfig) {
0328   if (iConfig.getParameter<bool>("computeMuonMVA")) {
0329     edm::FileInPath mvaTrainingFile = iConfig.getParameter<edm::FileInPath>("mvaTrainingFile");
0330     edm::FileInPath mvaLowPtTrainingFile = iConfig.getParameter<edm::FileInPath>("lowPtmvaTrainingFile");
0331     float mvaDrMax = iConfig.getParameter<double>("mvaDrMax");
0332     muonMvaEstimator_ = std::make_unique<MuonMvaEstimator>(mvaTrainingFile, mvaDrMax);
0333     muonLowPtMvaEstimator_ = std::make_unique<MuonMvaEstimator>(mvaLowPtTrainingFile, mvaDrMax);
0334   }
0335 
0336   if (iConfig.getParameter<bool>("computeMuonIDMVA")) {
0337     edm::FileInPath mvaIDTrainingFile = iConfig.getParameter<edm::FileInPath>("mvaIDTrainingFile");
0338     muonMvaIDEstimator_ = std::make_unique<MuonMvaIDEstimator>(mvaIDTrainingFile);
0339   }
0340 
0341   if (iConfig.getParameter<bool>("computeSoftMuonMVA")) {
0342     edm::FileInPath softMvaTrainingFile = iConfig.getParameter<edm::FileInPath>("softMvaTrainingFile");
0343     softMuonMvaEstimator_ = std::make_unique<SoftMuonMvaEstimator>(softMvaTrainingFile);
0344   }
0345 }
0346 
0347 PATMuonProducer::PATMuonProducer(const edm::ParameterSet& iConfig, PATMuonHeavyObjectCache const*)
0348     : relMiniIsoPUCorrected_(0),
0349       useUserData_(iConfig.exists("userData")),
0350       computeMuonMVA_(false),
0351       computeMuonIDMVA_(false),
0352       computeSoftMuonMVA_(false),
0353       recomputeBasicSelectors_(false),
0354       mvaUseJec_(false),
0355       isolator_(iConfig.getParameter<edm::ParameterSet>("userIsolation"), consumesCollector(), false),
0356       geometryToken_{esConsumes()},
0357       transientTrackBuilderToken_{esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))},
0358       patMuonPutToken_{produces<std::vector<Muon>>()} {
0359   // input source
0360   muonToken_ = consumes<edm::View<reco::Muon>>(iConfig.getParameter<edm::InputTag>("muonSource"));
0361   // embedding of tracks
0362   embedBestTrack_ = iConfig.getParameter<bool>("embedMuonBestTrack");
0363   embedTunePBestTrack_ = iConfig.getParameter<bool>("embedTunePMuonBestTrack");
0364   forceEmbedBestTrack_ = iConfig.getParameter<bool>("forceBestTrackEmbedding");
0365   embedTrack_ = iConfig.getParameter<bool>("embedTrack");
0366   embedCombinedMuon_ = iConfig.getParameter<bool>("embedCombinedMuon");
0367   embedStandAloneMuon_ = iConfig.getParameter<bool>("embedStandAloneMuon");
0368   // embedding of muon MET correction information
0369   embedCaloMETMuonCorrs_ = iConfig.getParameter<bool>("embedCaloMETMuonCorrs");
0370   embedTcMETMuonCorrs_ = iConfig.getParameter<bool>("embedTcMETMuonCorrs");
0371   caloMETMuonCorrsToken_ =
0372       mayConsume<edm::ValueMap<reco::MuonMETCorrectionData>>(iConfig.getParameter<edm::InputTag>("caloMETMuonCorrs"));
0373   tcMETMuonCorrsToken_ =
0374       mayConsume<edm::ValueMap<reco::MuonMETCorrectionData>>(iConfig.getParameter<edm::InputTag>("tcMETMuonCorrs"));
0375   // pflow specific configurables
0376   useParticleFlow_ = iConfig.getParameter<bool>("useParticleFlow");
0377   embedPFCandidate_ = iConfig.getParameter<bool>("embedPFCandidate");
0378   pfMuonToken_ = mayConsume<reco::PFCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfMuonSource"));
0379   embedPfEcalEnergy_ = iConfig.getParameter<bool>("embedPfEcalEnergy");
0380   // embedding of tracks from TeV refit
0381   embedPickyMuon_ = iConfig.getParameter<bool>("embedPickyMuon");
0382   embedTpfmsMuon_ = iConfig.getParameter<bool>("embedTpfmsMuon");
0383   embedDytMuon_ = iConfig.getParameter<bool>("embedDytMuon");
0384   // embedding of inverse beta variable information
0385   addInverseBeta_ = iConfig.getParameter<bool>("addInverseBeta");
0386   if (addInverseBeta_) {
0387     muonTimeExtraToken_ =
0388         consumes<edm::ValueMap<reco::MuonTimeExtra>>(iConfig.getParameter<edm::InputTag>("sourceMuonTimeExtra"));
0389   }
0390   // Monte Carlo matching
0391   addGenMatch_ = iConfig.getParameter<bool>("addGenMatch");
0392   if (addGenMatch_) {
0393     embedGenMatch_ = iConfig.getParameter<bool>("embedGenMatch");
0394     if (iConfig.existsAs<edm::InputTag>("genParticleMatch")) {
0395       genMatchTokens_.push_back(consumes<edm::Association<reco::GenParticleCollection>>(
0396           iConfig.getParameter<edm::InputTag>("genParticleMatch")));
0397     } else {
0398       genMatchTokens_ = edm::vector_transform(
0399           iConfig.getParameter<std::vector<edm::InputTag>>("genParticleMatch"),
0400           [this](edm::InputTag const& tag) { return consumes<edm::Association<reco::GenParticleCollection>>(tag); });
0401     }
0402   }
0403   // efficiencies
0404   addEfficiencies_ = iConfig.getParameter<bool>("addEfficiencies");
0405   if (addEfficiencies_) {
0406     efficiencyLoader_ =
0407         pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"), consumesCollector());
0408   }
0409   // resolutions
0410   addResolutions_ = iConfig.getParameter<bool>("addResolutions");
0411   if (addResolutions_) {
0412     resolutionLoader_ =
0413         pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"), consumesCollector());
0414   }
0415   // puppi
0416   addPuppiIsolation_ = iConfig.getParameter<bool>("addPuppiIsolation");
0417   if (addPuppiIsolation_) {
0418     PUPPIIsolation_charged_hadrons_ =
0419         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationChargedHadrons"));
0420     PUPPIIsolation_neutral_hadrons_ =
0421         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationNeutralHadrons"));
0422     PUPPIIsolation_photons_ =
0423         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationPhotons"));
0424     //puppiNoLeptons
0425     PUPPINoLeptonsIsolation_charged_hadrons_ =
0426         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationChargedHadrons"));
0427     PUPPINoLeptonsIsolation_neutral_hadrons_ =
0428         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationNeutralHadrons"));
0429     PUPPINoLeptonsIsolation_photons_ =
0430         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationPhotons"));
0431   }
0432   // read isoDeposit labels, for direct embedding
0433   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_, isoDepositTokens_);
0434   // read isolation value labels, for direct embedding
0435   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_, isolationValueTokens_);
0436   // check to see if the user wants to add user data
0437   if (useUserData_) {
0438     userDataHelper_ = PATUserDataHelper<Muon>(iConfig.getParameter<edm::ParameterSet>("userData"), consumesCollector());
0439   }
0440   // embed high level selection variables
0441   embedHighLevelSelection_ = iConfig.getParameter<bool>("embedHighLevelSelection");
0442   if (embedHighLevelSelection_) {
0443     beamLineToken_ = consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamLineSrc"));
0444     pvToken_ = consumes<std::vector<reco::Vertex>>(iConfig.getParameter<edm::InputTag>("pvSrc"));
0445   }
0446 
0447   //for mini-isolation calculation
0448   computeMiniIso_ = iConfig.getParameter<bool>("computeMiniIso");
0449 
0450   computePuppiCombinedIso_ = iConfig.getParameter<bool>("computePuppiCombinedIso");
0451 
0452   effectiveAreaVec_ = iConfig.getParameter<std::vector<double>>("effectiveAreaVec");
0453 
0454   miniIsoParams_ = iConfig.getParameter<std::vector<double>>("miniIsoParams");
0455   if (computeMiniIso_ && miniIsoParams_.size() != 9) {
0456     throw cms::Exception("ParameterError") << "miniIsoParams must have exactly 9 elements.\n";
0457   }
0458   if (computeMiniIso_ || computePuppiCombinedIso_)
0459     pcToken_ = consumes<pat::PackedCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfCandsForMiniIso"));
0460 
0461   // standard selectors
0462   recomputeBasicSelectors_ = iConfig.getParameter<bool>("recomputeBasicSelectors");
0463   computeMuonMVA_ = iConfig.getParameter<bool>("computeMuonMVA");
0464   computeMuonIDMVA_ = iConfig.getParameter<bool>("computeMuonIDMVA");
0465   if (computeMuonMVA_ and not computeMiniIso_)
0466     throw cms::Exception("ConfigurationError") << "MiniIso is needed for Muon MVA calculation.\n";
0467 
0468   if (computeMuonMVA_) {
0469     // pfCombinedInclusiveSecondaryVertexV2BJetTags
0470     mvaBTagCollectionTag_ = consumes<reco::JetTagCollection>(iConfig.getParameter<edm::InputTag>("mvaJetTag"));
0471     mvaL1Corrector_ = consumes<reco::JetCorrector>(iConfig.getParameter<edm::InputTag>("mvaL1Corrector"));
0472     mvaL1L2L3ResCorrector_ = consumes<reco::JetCorrector>(iConfig.getParameter<edm::InputTag>("mvaL1L2L3ResCorrector"));
0473     rho_ = consumes<double>(iConfig.getParameter<edm::InputTag>("rho"));
0474     mvaUseJec_ = iConfig.getParameter<bool>("mvaUseJec");
0475   }
0476 
0477   computeSoftMuonMVA_ = iConfig.getParameter<bool>("computeSoftMuonMVA");
0478 
0479   // MC info
0480   simInfo_ = consumes<edm::ValueMap<reco::MuonSimInfo>>(iConfig.getParameter<edm::InputTag>("muonSimInfo"));
0481 
0482   addTriggerMatching_ = iConfig.getParameter<bool>("addTriggerMatching");
0483   if (addTriggerMatching_) {
0484     triggerObjects_ =
0485         consumes<std::vector<pat::TriggerObjectStandAlone>>(iConfig.getParameter<edm::InputTag>("triggerObjects"));
0486     triggerResults_ = consumes<edm::TriggerResults>(iConfig.getParameter<edm::InputTag>("triggerResults"));
0487   }
0488   hltCollectionFilters_ = iConfig.getParameter<std::vector<std::string>>("hltCollectionFilters");
0489 }
0490 
0491 PATMuonProducer::~PATMuonProducer() {}
0492 
0493 std::optional<GlobalPoint> PATMuonProducer::getMuonDirection(const reco::MuonChamberMatch& chamberMatch,
0494                                                              const edm::ESHandle<GlobalTrackingGeometry>& geometry,
0495                                                              const DetId& chamberId) {
0496   const GeomDet* chamberGeometry = geometry->idToDet(chamberId);
0497   if (chamberGeometry) {
0498     LocalPoint localPosition(chamberMatch.x, chamberMatch.y, 0);
0499     return std::optional<GlobalPoint>(std::in_place, chamberGeometry->toGlobal(localPosition));
0500   }
0501   return std::optional<GlobalPoint>();
0502 }
0503 
0504 void PATMuonProducer::fillL1TriggerInfo(pat::Muon& aMuon,
0505                                         edm::Handle<std::vector<pat::TriggerObjectStandAlone>>& triggerObjects,
0506                                         const edm::TriggerNames& names,
0507                                         const edm::ESHandle<GlobalTrackingGeometry>& geometry) {
0508   // L1 trigger object parameters are defined at MB2/ME2. Use the muon
0509   // chamber matching information to get the local direction of the
0510   // muon trajectory and convert it to a global direction to match the
0511   // trigger objects
0512 
0513   std::optional<GlobalPoint> muonPosition;
0514   // Loop over chambers
0515   // initialize muonPosition with any available match, just in case
0516   // the second station is missing - it's better folling back to
0517   // dR matching at IP
0518   for (const auto& chamberMatch : aMuon.matches()) {
0519     if (chamberMatch.id.subdetId() == MuonSubdetId::DT) {
0520       DTChamberId detId(chamberMatch.id.rawId());
0521       if (abs(detId.station()) > 3)
0522         continue;
0523       muonPosition = getMuonDirection(chamberMatch, geometry, detId);
0524       if (abs(detId.station()) == 2)
0525         break;
0526     }
0527     if (chamberMatch.id.subdetId() == MuonSubdetId::CSC) {
0528       CSCDetId detId(chamberMatch.id.rawId());
0529       if (abs(detId.station()) > 3)
0530         continue;
0531       muonPosition = getMuonDirection(chamberMatch, geometry, detId);
0532       if (abs(detId.station()) == 2)
0533         break;
0534     }
0535   }
0536   if (not muonPosition)
0537     return;
0538   for (const auto& triggerObject : *triggerObjects) {
0539     if (triggerObject.hasTriggerObjectType(trigger::TriggerL1Mu)) {
0540       if (std::abs(triggerObject.eta()) < 0.001) {
0541         // L1 is defined in X-Y plain
0542         if (deltaPhi(triggerObject.phi(), muonPosition->phi()) > 0.1)
0543           continue;
0544       } else {
0545         // 3D L1
0546         if (deltaR(triggerObject.p4(), *muonPosition) > 0.15)
0547           continue;
0548       }
0549       pat::TriggerObjectStandAlone obj(triggerObject);
0550       obj.unpackPathNames(names);
0551       aMuon.addTriggerObjectMatch(obj);
0552     }
0553   }
0554 }
0555 
0556 void PATMuonProducer::fillHltTriggerInfo(pat::Muon& muon,
0557                                          edm::Handle<std::vector<pat::TriggerObjectStandAlone>>& triggerObjects,
0558                                          const edm::TriggerNames& names,
0559                                          const std::vector<std::string>& collection_filter_names) {
0560   // WARNING: in a case of close-by muons the dR matching may select both muons.
0561   // It's better to select the best match for a given collection.
0562   for (const auto& triggerObject : *triggerObjects) {
0563     if (triggerObject.hasTriggerObjectType(trigger::TriggerMuon)) {
0564       bool keepIt = false;
0565       for (const auto& name : collection_filter_names) {
0566         if (triggerObject.hasCollection(name)) {
0567           keepIt = true;
0568           break;
0569         }
0570       }
0571       if (not keepIt)
0572         continue;
0573       if (deltaR(triggerObject.p4(), muon) > 0.1)
0574         continue;
0575       pat::TriggerObjectStandAlone obj(triggerObject);
0576       obj.unpackPathNames(names);
0577       muon.addTriggerObjectMatch(obj);
0578     }
0579   }
0580 }
0581 
0582 void PATMuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0583   // get the tracking Geometry
0584   auto geometry = iSetup.getHandle(geometryToken_);
0585   if (!geometry.isValid())
0586     throw cms::Exception("FatalError") << "Unable to find GlobalTrackingGeometryRecord in event!\n";
0587 
0588   // switch off embedding (in unschedules mode)
0589   if (iEvent.isRealData()) {
0590     addGenMatch_ = false;
0591     embedGenMatch_ = false;
0592   }
0593 
0594   edm::Handle<edm::View<reco::Muon>> muons;
0595   iEvent.getByToken(muonToken_, muons);
0596 
0597   edm::Handle<pat::PackedCandidateCollection> pc;
0598   if (computeMiniIso_ || computePuppiCombinedIso_)
0599     iEvent.getByToken(pcToken_, pc);
0600 
0601   // get the ESHandle for the transient track builder,
0602   // if needed for high level selection embedding
0603   TransientTrackBuilder const* trackBuilder = nullptr;
0604 
0605   if (isolator_.enabled())
0606     isolator_.beginEvent(iEvent, iSetup);
0607   if (efficiencyLoader_.enabled())
0608     efficiencyLoader_.newEvent(iEvent);
0609   if (resolutionLoader_.enabled())
0610     resolutionLoader_.newEvent(iEvent, iSetup);
0611 
0612   IsoDepositMaps deposits(isoDepositTokens_.size());
0613   for (size_t j = 0; j < isoDepositTokens_.size(); ++j) {
0614     iEvent.getByToken(isoDepositTokens_[j], deposits[j]);
0615   }
0616 
0617   IsolationValueMaps isolationValues(isolationValueTokens_.size());
0618   for (size_t j = 0; j < isolationValueTokens_.size(); ++j) {
0619     iEvent.getByToken(isolationValueTokens_[j], isolationValues[j]);
0620   }
0621 
0622   //value maps for puppi isolation
0623   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons;
0624   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons;
0625   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_photons;
0626   //value maps for puppiNoLeptons isolation
0627   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_charged_hadrons;
0628   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_neutral_hadrons;
0629   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_photons;
0630   if (addPuppiIsolation_) {
0631     //puppi
0632     iEvent.getByToken(PUPPIIsolation_charged_hadrons_, PUPPIIsolation_charged_hadrons);
0633     iEvent.getByToken(PUPPIIsolation_neutral_hadrons_, PUPPIIsolation_neutral_hadrons);
0634     iEvent.getByToken(PUPPIIsolation_photons_, PUPPIIsolation_photons);
0635     //puppiNoLeptons
0636     iEvent.getByToken(PUPPINoLeptonsIsolation_charged_hadrons_, PUPPINoLeptonsIsolation_charged_hadrons);
0637     iEvent.getByToken(PUPPINoLeptonsIsolation_neutral_hadrons_, PUPPINoLeptonsIsolation_neutral_hadrons);
0638     iEvent.getByToken(PUPPINoLeptonsIsolation_photons_, PUPPINoLeptonsIsolation_photons);
0639   }
0640 
0641   // inputs for muon mva
0642   edm::Handle<reco::JetTagCollection> mvaBTagCollectionTag;
0643   edm::Handle<reco::JetCorrector> mvaL1Corrector;
0644   edm::Handle<reco::JetCorrector> mvaL1L2L3ResCorrector;
0645   if (computeMuonMVA_) {
0646     iEvent.getByToken(mvaBTagCollectionTag_, mvaBTagCollectionTag);
0647     iEvent.getByToken(mvaL1Corrector_, mvaL1Corrector);
0648     iEvent.getByToken(mvaL1L2L3ResCorrector_, mvaL1L2L3ResCorrector);
0649   }
0650 
0651   // prepare the MC genMatchTokens_
0652   GenAssociations genMatches(genMatchTokens_.size());
0653   if (addGenMatch_) {
0654     for (size_t j = 0, nd = genMatchTokens_.size(); j < nd; ++j) {
0655       iEvent.getByToken(genMatchTokens_[j], genMatches[j]);
0656     }
0657   }
0658 
0659   // prepare the high level selection: needs beamline
0660   // OR primary vertex, depending on user selection
0661   reco::Vertex primaryVertex;
0662   reco::BeamSpot beamSpot;
0663   bool beamSpotIsValid = false;
0664   bool primaryVertexIsValid = false;
0665   if (embedHighLevelSelection_) {
0666     // get the beamspot
0667     edm::Handle<reco::BeamSpot> beamSpotHandle;
0668     iEvent.getByToken(beamLineToken_, beamSpotHandle);
0669 
0670     // get the primary vertex
0671     edm::Handle<std::vector<reco::Vertex>> pvHandle;
0672     iEvent.getByToken(pvToken_, pvHandle);
0673 
0674     if (beamSpotHandle.isValid()) {
0675       beamSpot = *beamSpotHandle;
0676       beamSpotIsValid = true;
0677     } else {
0678       edm::LogError("DataNotAvailable") << "No beam spot available from EventSetup, not adding high level selection \n";
0679     }
0680     if (pvHandle.isValid() && !pvHandle->empty()) {
0681       primaryVertex = pvHandle->at(0);
0682       primaryVertexIsValid = true;
0683     } else {
0684       edm::LogError("DataNotAvailable")
0685           << "No primary vertex available from EventSetup, not adding high level selection \n";
0686     }
0687     // this is needed by the IPTools methods from the tracking group
0688     trackBuilder = &iSetup.getData(transientTrackBuilderToken_);
0689   }
0690 
0691   // MC info
0692   edm::Handle<edm::ValueMap<reco::MuonSimInfo>> simInfo;
0693   bool simInfoIsAvailalbe = iEvent.getByToken(simInfo_, simInfo);
0694 
0695   // this will be the new object collection
0696   std::vector<Muon> patMuons;
0697 
0698   edm::Handle<reco::PFCandidateCollection> pfMuons;
0699   if (useParticleFlow_) {
0700     // get the PFCandidates of type muons
0701     iEvent.getByToken(pfMuonToken_, pfMuons);
0702 
0703     unsigned index = 0;
0704     for (reco::PFCandidateConstIterator i = pfMuons->begin(); i != pfMuons->end(); ++i, ++index) {
0705       const reco::PFCandidate& pfmu = *i;
0706       //const reco::IsolaPFCandidate& pfmu = *i;
0707       const reco::MuonRef& muonRef = pfmu.muonRef();
0708       assert(muonRef.isNonnull());
0709 
0710       MuonBaseRef muonBaseRef(muonRef);
0711       Muon aMuon(muonBaseRef);
0712 
0713       if (useUserData_) {
0714         userDataHelper_.add(aMuon, iEvent, iSetup);
0715       }
0716 
0717       // embed high level selection
0718       if (embedHighLevelSelection_) {
0719         // get the tracks
0720         reco::TrackRef innerTrack = muonBaseRef->innerTrack();
0721         reco::TrackRef globalTrack = muonBaseRef->globalTrack();
0722         reco::TrackRef bestTrack = muonBaseRef->muonBestTrack();
0723         reco::TrackRef chosenTrack = innerTrack;
0724         // Make sure the collection it points to is there
0725         if (bestTrack.isNonnull() && bestTrack.isAvailable())
0726           chosenTrack = bestTrack;
0727 
0728         if (chosenTrack.isNonnull() && chosenTrack.isAvailable()) {
0729           unsigned int nhits = chosenTrack->numberOfValidHits();  // ????
0730           aMuon.setNumberOfValidHits(nhits);
0731 
0732           reco::TransientTrack tt = trackBuilder->build(chosenTrack);
0733           embedHighLevel(aMuon, chosenTrack, tt, primaryVertex, primaryVertexIsValid, beamSpot, beamSpotIsValid);
0734         }
0735 
0736         if (globalTrack.isNonnull() && globalTrack.isAvailable() && !embedCombinedMuon_) {
0737           double norm_chi2 = globalTrack->chi2() / globalTrack->ndof();
0738           aMuon.setNormChi2(norm_chi2);
0739         }
0740       }
0741       reco::PFCandidateRef pfRef(pfMuons, index);
0742       //reco::PFCandidatePtr ptrToMother(pfMuons,index);
0743       reco::CandidateBaseRef pfBaseRef(pfRef);
0744 
0745       aMuon.setPFCandidateRef(pfRef);
0746       if (embedPFCandidate_)
0747         aMuon.embedPFCandidate();
0748       fillMuon(aMuon, muonBaseRef, pfBaseRef, genMatches, deposits, isolationValues);
0749 
0750       if (computeMiniIso_)
0751         setMuonMiniIso(aMuon, pc.product());
0752 
0753       if (addPuppiIsolation_) {
0754         aMuon.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[muonBaseRef],
0755                                 (*PUPPIIsolation_neutral_hadrons)[muonBaseRef],
0756                                 (*PUPPIIsolation_photons)[muonBaseRef]);
0757 
0758         aMuon.setIsolationPUPPINoLeptons((*PUPPINoLeptonsIsolation_charged_hadrons)[muonBaseRef],
0759                                          (*PUPPINoLeptonsIsolation_neutral_hadrons)[muonBaseRef],
0760                                          (*PUPPINoLeptonsIsolation_photons)[muonBaseRef]);
0761       } else {
0762         aMuon.setIsolationPUPPI(-999., -999., -999.);
0763         aMuon.setIsolationPUPPINoLeptons(-999., -999., -999.);
0764       }
0765 
0766       if (embedPfEcalEnergy_) {
0767         aMuon.setPfEcalEnergy(pfmu.ecalEnergy());
0768       }
0769 
0770       patMuons.push_back(aMuon);
0771     }
0772   } else {
0773     edm::Handle<edm::View<reco::Muon>> muons;
0774     iEvent.getByToken(muonToken_, muons);
0775 
0776     // embedding of muon MET corrections
0777     edm::Handle<edm::ValueMap<reco::MuonMETCorrectionData>> caloMETMuonCorrs;
0778     //edm::ValueMap<reco::MuonMETCorrectionData> caloMETmuCorValueMap;
0779     if (embedCaloMETMuonCorrs_) {
0780       iEvent.getByToken(caloMETMuonCorrsToken_, caloMETMuonCorrs);
0781       //caloMETmuCorValueMap  = *caloMETmuCorValueMap_h;
0782     }
0783     edm::Handle<edm::ValueMap<reco::MuonMETCorrectionData>> tcMETMuonCorrs;
0784     //edm::ValueMap<reco::MuonMETCorrectionData> tcMETmuCorValueMap;
0785     if (embedTcMETMuonCorrs_) {
0786       iEvent.getByToken(tcMETMuonCorrsToken_, tcMETMuonCorrs);
0787       //tcMETmuCorValueMap  = *tcMETmuCorValueMap_h;
0788     }
0789 
0790     if (embedPfEcalEnergy_ || embedPFCandidate_) {
0791       // get the PFCandidates of type muons
0792       iEvent.getByToken(pfMuonToken_, pfMuons);
0793     }
0794 
0795     edm::Handle<edm::ValueMap<reco::MuonTimeExtra>> muonsTimeExtra;
0796     if (addInverseBeta_) {
0797       // get MuonTimerExtra value map
0798       iEvent.getByToken(muonTimeExtraToken_, muonsTimeExtra);
0799     }
0800 
0801     for (edm::View<reco::Muon>::const_iterator itMuon = muons->begin(); itMuon != muons->end(); ++itMuon) {
0802       // construct the Muon from the ref -> save ref to original object
0803       unsigned int idx = itMuon - muons->begin();
0804       MuonBaseRef muonRef = muons->refAt(idx);
0805       reco::CandidateBaseRef muonBaseRef(muonRef);
0806 
0807       Muon aMuon(muonRef);
0808       fillMuon(aMuon, muonRef, muonBaseRef, genMatches, deposits, isolationValues);
0809       if (computeMiniIso_)
0810         setMuonMiniIso(aMuon, pc.product());
0811       if (addPuppiIsolation_) {
0812         aMuon.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[muonRef],
0813                                 (*PUPPIIsolation_neutral_hadrons)[muonRef],
0814                                 (*PUPPIIsolation_photons)[muonRef]);
0815         aMuon.setIsolationPUPPINoLeptons((*PUPPINoLeptonsIsolation_charged_hadrons)[muonRef],
0816                                          (*PUPPINoLeptonsIsolation_neutral_hadrons)[muonRef],
0817                                          (*PUPPINoLeptonsIsolation_photons)[muonRef]);
0818       } else {
0819         aMuon.setIsolationPUPPI(-999., -999., -999.);
0820         aMuon.setIsolationPUPPINoLeptons(-999., -999., -999.);
0821       }
0822 
0823       // Isolation
0824       if (isolator_.enabled()) {
0825         //reco::CandidatePtr mother =  ptrToMother->sourceCandidatePtr(0);
0826         isolator_.fill(*muons, idx, isolatorTmpStorage_);
0827         typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
0828         // better to loop backwards, so the vector is resized less times
0829         for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(),
0830                                                          ed = isolatorTmpStorage_.rend();
0831              it != ed;
0832              ++it) {
0833           aMuon.setIsolation(it->first, it->second);
0834         }
0835       }
0836 
0837       //       for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
0838       //    aMuon.setIsoDeposit(isoDepositLabels_[j].first,
0839       //                (*deposits[j])[muonRef]);
0840       //       }
0841 
0842       // add sel to selected
0843       edm::Ptr<reco::Muon> muonsPtr = muons->ptrAt(idx);
0844       if (useUserData_) {
0845         userDataHelper_.add(aMuon, iEvent, iSetup);
0846       }
0847 
0848       // embed high level selection
0849       if (embedHighLevelSelection_) {
0850         // get the tracks
0851         reco::TrackRef innerTrack = itMuon->innerTrack();
0852         reco::TrackRef globalTrack = itMuon->globalTrack();
0853         reco::TrackRef bestTrack = itMuon->muonBestTrack();
0854         reco::TrackRef chosenTrack = innerTrack;
0855         // Make sure the collection it points to is there
0856         if (bestTrack.isNonnull() && bestTrack.isAvailable())
0857           chosenTrack = bestTrack;
0858         if (chosenTrack.isNonnull() && chosenTrack.isAvailable()) {
0859           unsigned int nhits = chosenTrack->numberOfValidHits();  // ????
0860           aMuon.setNumberOfValidHits(nhits);
0861 
0862           reco::TransientTrack tt = trackBuilder->build(chosenTrack);
0863           embedHighLevel(aMuon, chosenTrack, tt, primaryVertex, primaryVertexIsValid, beamSpot, beamSpotIsValid);
0864         }
0865 
0866         if (globalTrack.isNonnull() && globalTrack.isAvailable()) {
0867           double norm_chi2 = globalTrack->chi2() / globalTrack->ndof();
0868           aMuon.setNormChi2(norm_chi2);
0869         }
0870       }
0871 
0872       // embed MET muon corrections
0873       if (embedCaloMETMuonCorrs_)
0874         aMuon.embedCaloMETMuonCorrs((*caloMETMuonCorrs)[muonRef]);
0875       if (embedTcMETMuonCorrs_)
0876         aMuon.embedTcMETMuonCorrs((*tcMETMuonCorrs)[muonRef]);
0877 
0878       if (embedPfEcalEnergy_ || embedPFCandidate_) {
0879         if (embedPfEcalEnergy_)
0880           aMuon.setPfEcalEnergy(-99.0);
0881         unsigned index = 0;
0882         for (const reco::PFCandidate& pfmu : *pfMuons) {
0883           if (pfmu.muonRef().isNonnull()) {
0884             if (pfmu.muonRef().id() != muonRef.id())
0885               throw cms::Exception("Configuration")
0886                   << "Muon reference within PF candidates does not point to the muon collection." << std::endl;
0887             if (pfmu.muonRef().key() == muonRef.key()) {
0888               reco::PFCandidateRef pfRef(pfMuons, index);
0889               aMuon.setPFCandidateRef(pfRef);
0890               if (embedPfEcalEnergy_)
0891                 aMuon.setPfEcalEnergy(pfmu.ecalEnergy());
0892               if (embedPFCandidate_)
0893                 aMuon.embedPFCandidate();
0894               break;
0895             }
0896           }
0897           index++;
0898         }
0899       }
0900 
0901       if (addInverseBeta_) {
0902         aMuon.readTimeExtra((*muonsTimeExtra)[muonRef]);
0903       }
0904       // MC info
0905       aMuon.initSimInfo();
0906       if (simInfoIsAvailalbe) {
0907         const auto& msi = (*simInfo)[muonBaseRef];
0908         aMuon.setSimType(msi.primaryClass);
0909         aMuon.setExtSimType(msi.extendedClass);
0910         aMuon.setSimFlavour(msi.flavour);
0911         aMuon.setSimHeaviestMotherFlavour(msi.heaviestMotherFlavour);
0912         aMuon.setSimPdgId(msi.pdgId);
0913         aMuon.setSimMotherPdgId(msi.motherPdgId);
0914         aMuon.setSimBX(msi.tpBX);
0915         aMuon.setSimTpEvent(msi.tpEvent);
0916         aMuon.setSimProdRho(msi.vertex.Rho());
0917         aMuon.setSimProdZ(msi.vertex.Z());
0918         aMuon.setSimPt(msi.p4.pt());
0919         aMuon.setSimEta(msi.p4.eta());
0920         aMuon.setSimPhi(msi.p4.phi());
0921         aMuon.setSimMatchQuality(msi.tpAssoQuality);
0922       }
0923       patMuons.push_back(aMuon);
0924     }
0925   }
0926 
0927   // sort muons in pt
0928   std::sort(patMuons.begin(), patMuons.end(), [](auto const& t1, auto const& t2) { return t1.pt() > t2.pt(); });
0929 
0930   // Store standard muon selection decisions and jet related
0931   // quantaties.
0932   // Need a separate loop over muons to have all inputs properly
0933   // computed and stored in the object.
0934   edm::Handle<double> rho;
0935   if (computeMuonMVA_)
0936     iEvent.getByToken(rho_, rho);
0937   const reco::Vertex* pv(nullptr);
0938   if (primaryVertexIsValid)
0939     pv = &primaryVertex;
0940 
0941   edm::Handle<std::vector<pat::TriggerObjectStandAlone>> triggerObjects;
0942   edm::Handle<edm::TriggerResults> triggerResults;
0943   bool triggerObjectsAvailable = false;
0944   bool triggerResultsAvailable = false;
0945   if (addTriggerMatching_) {
0946     triggerObjectsAvailable = iEvent.getByToken(triggerObjects_, triggerObjects);
0947     triggerResultsAvailable = iEvent.getByToken(triggerResults_, triggerResults);
0948   }
0949 
0950   for (auto& muon : patMuons) {
0951     // trigger info
0952     if (addTriggerMatching_ and triggerObjectsAvailable and triggerResultsAvailable) {
0953       const edm::TriggerNames& triggerNames(iEvent.triggerNames(*triggerResults));
0954       fillL1TriggerInfo(muon, triggerObjects, triggerNames, geometry);
0955       fillHltTriggerInfo(muon, triggerObjects, triggerNames, hltCollectionFilters_);
0956     }
0957 
0958     if (recomputeBasicSelectors_) {
0959       muon.setSelectors(0);
0960       bool isRun2016BCDEF = (272728 <= iEvent.run() && iEvent.run() <= 278808);
0961       muon.setSelectors(muon::makeSelectorBitset(muon, pv, isRun2016BCDEF));
0962     }
0963     float miniIsoValue = -1;
0964     if (computeMiniIso_) {
0965       // MiniIsolation working points
0966 
0967       miniIsoValue = getRelMiniIsoPUCorrected(muon, *rho, effectiveAreaVec_);
0968 
0969       muon.setSelector(reco::Muon::MiniIsoLoose, miniIsoValue < 0.40);
0970       muon.setSelector(reco::Muon::MiniIsoMedium, miniIsoValue < 0.20);
0971       muon.setSelector(reco::Muon::MiniIsoTight, miniIsoValue < 0.10);
0972       muon.setSelector(reco::Muon::MiniIsoVeryTight, miniIsoValue < 0.05);
0973     }
0974 
0975     double puppiCombinedIsolationPAT = -1;
0976     if (computePuppiCombinedIso_) {
0977       puppiCombinedIsolationPAT = puppiCombinedIsolation(muon, pc.product());
0978       muon.setSelector(reco::Muon::PuppiIsoLoose, puppiCombinedIsolationPAT < 0.27);
0979       muon.setSelector(reco::Muon::PuppiIsoMedium, puppiCombinedIsolationPAT < 0.22);
0980       muon.setSelector(reco::Muon::PuppiIsoTight, puppiCombinedIsolationPAT < 0.12);
0981     }
0982 
0983     float jetPtRatio = 0.0;
0984     float jetPtRel = 0.0;
0985     float mva = 0.0;
0986     float mva_lowpt = 0.0;
0987     if (computeMuonMVA_ && primaryVertexIsValid && computeMiniIso_) {
0988       if (mvaUseJec_) {
0989         mva = globalCache()->muonMvaEstimator().computeMva(muon,
0990                                                            primaryVertex,
0991                                                            *(mvaBTagCollectionTag.product()),
0992                                                            jetPtRatio,
0993                                                            jetPtRel,
0994                                                            miniIsoValue,
0995                                                            mvaL1Corrector.product(),
0996                                                            mvaL1L2L3ResCorrector.product());
0997         mva_lowpt = globalCache()->muonLowPtMvaEstimator().computeMva(muon,
0998                                                                       primaryVertex,
0999                                                                       *(mvaBTagCollectionTag.product()),
1000                                                                       jetPtRatio,
1001                                                                       jetPtRel,
1002                                                                       miniIsoValue,
1003                                                                       mvaL1Corrector.product(),
1004                                                                       mvaL1L2L3ResCorrector.product());
1005 
1006       } else {
1007         mva = globalCache()->muonMvaEstimator().computeMva(
1008             muon, primaryVertex, *mvaBTagCollectionTag, jetPtRatio, jetPtRel, miniIsoValue);
1009         mva_lowpt = globalCache()->muonLowPtMvaEstimator().computeMva(
1010             muon, primaryVertex, *mvaBTagCollectionTag, jetPtRatio, jetPtRel, miniIsoValue);
1011       }
1012 
1013       muon.setMvaValue(mva);
1014       muon.setLowPtMvaValue(mva_lowpt);
1015       muon.setJetPtRatio(jetPtRatio);
1016       muon.setJetPtRel(jetPtRel);
1017 
1018       // multi-isolation
1019       if (computeMiniIso_) {
1020         muon.setSelector(reco::Muon::MultiIsoMedium,
1021                          miniIsoValue < 0.11 && (muon.jetPtRatio() > 0.74 || muon.jetPtRel() > 6.8));
1022       }
1023 
1024       // MVA working points
1025       // https://twiki.cern.ch/twiki/bin/viewauth/CMS/LeptonMVA
1026       const double dB2D = std::abs(muon.dB(pat::Muon::PV2D));
1027       const double dB3D = std::abs(muon.dB(pat::Muon::PV3D));
1028       const double edB3D = std::abs(muon.edB(pat::Muon::PV3D));
1029       const double sip3D = edB3D > 0 ? dB3D / edB3D : 0.0;
1030       const double dz = std::abs(muon.muonBestTrack()->dz(primaryVertex.position()));
1031 
1032       // muon preselection
1033       if (muon.pt() > 5 and muon.isLooseMuon() and muon.passed(reco::Muon::MiniIsoLoose) and sip3D < 8.0 and
1034           dB2D < 0.05 and dz < 0.1) {
1035         muon.setSelector(reco::Muon::MvaLoose, muon.mvaValue() > -0.60);
1036         muon.setSelector(reco::Muon::MvaMedium, muon.mvaValue() > -0.20);
1037         muon.setSelector(reco::Muon::MvaTight, muon.mvaValue() > 0.15);
1038         muon.setSelector(reco::Muon::MvaVTight, muon.mvaValue() > 0.45);
1039         muon.setSelector(reco::Muon::MvaVVTight, muon.mvaValue() > 0.9);
1040       }
1041       if (muon.pt() > 5 and muon.isLooseMuon() and sip3D < 4 and dB2D < 0.5 and dz < 1) {
1042         muon.setSelector(reco::Muon::LowPtMvaLoose, muon.lowptMvaValue() > -0.60);
1043         muon.setSelector(reco::Muon::LowPtMvaMedium, muon.lowptMvaValue() > -0.20);
1044       }
1045     }
1046 
1047     // MVA ID
1048     float mvaID = 0.0;
1049     constexpr int MVAsentinelValue = -99;
1050     constexpr float mvaIDmediumCut = 0.08;
1051     constexpr float mvaIDtightCut = 0.12;
1052     if (computeMuonIDMVA_) {
1053       const double dz = std::abs(muon.muonBestTrack()->dz(primaryVertex.position()));
1054       const double dxy = std::abs(muon.muonBestTrack()->dxy(primaryVertex.position()));
1055       if (muon.isLooseMuon()) {
1056         mvaID = globalCache()->muonMvaIDEstimator().computeMVAID(muon)[1];
1057       } else {
1058         mvaID = MVAsentinelValue;
1059       }
1060       muon.setMvaIDValue(mvaID);
1061       muon.setSelector(reco::Muon::MvaIDwpMedium, muon.mvaIDValue() > mvaIDmediumCut);
1062       muon.setSelector(reco::Muon::MvaIDwpTight, muon.mvaIDValue() > mvaIDtightCut and dz < 0.5 and dxy < 0.2);
1063     }
1064 
1065     //SOFT MVA
1066     if (computeSoftMuonMVA_) {
1067       float mva = globalCache()->softMuonMvaEstimator().computeMva(muon);
1068       muon.setSoftMvaValue(mva);
1069       //preselection in SoftMuonMvaEstimator.cc
1070       muon.setSelector(reco::Muon::SoftMvaId, muon.softMvaValue() > 0.58);  //WP choose for bmm4
1071     }
1072   }
1073 
1074   // put products in Event
1075   iEvent.emplace(patMuonPutToken_, std::move(patMuons));
1076 
1077   if (isolator_.enabled())
1078     isolator_.endEvent();
1079 }
1080 
1081 void PATMuonProducer::fillMuon(Muon& aMuon,
1082                                const MuonBaseRef& muonRef,
1083                                const reco::CandidateBaseRef& baseRef,
1084                                const GenAssociations& genMatches,
1085                                const IsoDepositMaps& deposits,
1086                                const IsolationValueMaps& isolationValues) const {
1087   // in the particle flow algorithm,
1088   // the muon momentum is recomputed.
1089   // the new value is stored as the momentum of the
1090   // resulting PFCandidate of type Muon, and choosen
1091   // as the pat::Muon momentum
1092   if (useParticleFlow_)
1093     aMuon.setP4(aMuon.pfCandidateRef()->p4());
1094   if (embedTrack_)
1095     aMuon.embedTrack();
1096   if (embedStandAloneMuon_)
1097     aMuon.embedStandAloneMuon();
1098   if (embedCombinedMuon_)
1099     aMuon.embedCombinedMuon();
1100 
1101   // embed the TeV refit track refs (only available for globalMuons)
1102   if (aMuon.isGlobalMuon()) {
1103     if (embedPickyMuon_ && aMuon.isAValidMuonTrack(reco::Muon::Picky))
1104       aMuon.embedPickyMuon();
1105     if (embedTpfmsMuon_ && aMuon.isAValidMuonTrack(reco::Muon::TPFMS))
1106       aMuon.embedTpfmsMuon();
1107     if (embedDytMuon_ && aMuon.isAValidMuonTrack(reco::Muon::DYT))
1108       aMuon.embedDytMuon();
1109   }
1110 
1111   // embed best tracks (at the end, so unless forceEmbedBestTrack_ is true we can save some space not embedding them twice)
1112   if (embedBestTrack_)
1113     aMuon.embedMuonBestTrack(forceEmbedBestTrack_);
1114   if (embedTunePBestTrack_)
1115     aMuon.embedTunePMuonBestTrack(forceEmbedBestTrack_);
1116 
1117   // store the match to the generated final state muons
1118   if (addGenMatch_) {
1119     for (auto const& genMatch : genMatches) {
1120       reco::GenParticleRef genMuon = (*genMatch)[baseRef];
1121       aMuon.addGenParticleRef(genMuon);
1122     }
1123     if (embedGenMatch_)
1124       aMuon.embedGenParticle();
1125   }
1126   if (efficiencyLoader_.enabled()) {
1127     efficiencyLoader_.setEfficiencies(aMuon, muonRef);
1128   }
1129 
1130   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
1131     if (useParticleFlow_) {
1132       if (deposits[j]->contains(baseRef.id())) {
1133         aMuon.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[baseRef]);
1134       } else if (deposits[j]->contains(muonRef.id())) {
1135         aMuon.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[muonRef]);
1136       } else {
1137         reco::CandidatePtr source = aMuon.pfCandidateRef()->sourceCandidatePtr(0);
1138         aMuon.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[source]);
1139       }
1140     } else {
1141       aMuon.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[muonRef]);
1142     }
1143   }
1144 
1145   for (size_t j = 0; j < isolationValues.size(); ++j) {
1146     if (useParticleFlow_) {
1147       if (isolationValues[j]->contains(baseRef.id())) {
1148         aMuon.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[baseRef]);
1149       } else if (isolationValues[j]->contains(muonRef.id())) {
1150         aMuon.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[muonRef]);
1151       } else {
1152         reco::CandidatePtr source = aMuon.pfCandidateRef()->sourceCandidatePtr(0);
1153         aMuon.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[source]);
1154       }
1155     } else {
1156       aMuon.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[muonRef]);
1157     }
1158   }
1159 
1160   if (resolutionLoader_.enabled()) {
1161     resolutionLoader_.setResolutions(aMuon);
1162   }
1163 }
1164 
1165 void PATMuonProducer::setMuonMiniIso(Muon& aMuon, const PackedCandidateCollection* pc) {
1166   pat::PFIsolation miniiso = pat::getMiniPFIsolation(pc,
1167                                                      aMuon.polarP4(),
1168                                                      miniIsoParams_[0],
1169                                                      miniIsoParams_[1],
1170                                                      miniIsoParams_[2],
1171                                                      miniIsoParams_[3],
1172                                                      miniIsoParams_[4],
1173                                                      miniIsoParams_[5],
1174                                                      miniIsoParams_[6],
1175                                                      miniIsoParams_[7],
1176                                                      miniIsoParams_[8]);
1177   aMuon.setMiniPFIsolation(miniiso);
1178 }
1179 
1180 double PATMuonProducer::getRelMiniIsoPUCorrected(const pat::Muon& muon, double rho, const std::vector<double>& area) {
1181   double mindr(miniIsoParams_[0]);
1182   double maxdr(miniIsoParams_[1]);
1183   double kt_scale(miniIsoParams_[2]);
1184   double drcut = pat::miniIsoDr(muon.polarP4(), mindr, maxdr, kt_scale);
1185   return pat::muonRelMiniIsoPUCorrected(muon.miniPFIsolation(), muon.polarP4(), drcut, rho, area);
1186 }
1187 
1188 double PATMuonProducer::puppiCombinedIsolation(const pat::Muon& muon, const pat::PackedCandidateCollection* pc) {
1189   constexpr double dR_threshold = 0.4;
1190   constexpr double dR2_threshold = dR_threshold * dR_threshold;
1191   constexpr double mix_fraction = 0.5;
1192   enum particleType { CH = 0, NH = 1, PH = 2, OTHER = 100000 };
1193   double val_PuppiWithLep = 0.0;
1194   double val_PuppiWithoutLep = 0.0;
1195 
1196   for (const auto& cand : *pc) {  //pat::pat::PackedCandidate loop start
1197 
1198     const particleType pType = isChargedHadron(cand.pdgId())   ? CH
1199                                : isNeutralHadron(cand.pdgId()) ? NH
1200                                : isPhoton(cand.pdgId())        ? PH
1201                                                                : OTHER;
1202     if (pType == OTHER) {
1203       if (cand.pdgId() != 1 && cand.pdgId() != 2 && abs(cand.pdgId()) != 11 && abs(cand.pdgId()) != 13) {
1204         LogTrace("PATMuonProducer") << "candidate with PDGID = " << cand.pdgId()
1205                                     << " is not CH/NH/PH/e/mu or 1/2 (and this is removed from isolation calculation)"
1206                                     << std::endl;
1207       }
1208       continue;
1209     }
1210     double d_eta = std::abs(cand.eta() - muon.eta());
1211     if (d_eta > dR_threshold)
1212       continue;
1213 
1214     double d_phi = std::abs(reco::deltaPhi(cand.phi(), muon.phi()));
1215     if (d_phi > dR_threshold)
1216       continue;
1217 
1218     double dR2 = reco::deltaR2(cand, muon);
1219     if (dR2 > dR2_threshold)
1220       continue;
1221     if (pType == CH && dR2 < 0.0001 * 0.0001)
1222       continue;
1223     if (pType == NH && dR2 < 0.01 * 0.01)
1224       continue;
1225     if (pType == PH && dR2 < 0.01 * 0.01)
1226       continue;
1227     val_PuppiWithLep += cand.pt() * cand.puppiWeight();
1228     val_PuppiWithoutLep += cand.pt() * cand.puppiWeightNoLep();
1229 
1230   }  //pat::pat::PackedCandidate loop end
1231 
1232   double reliso_Puppi_withLep = val_PuppiWithLep / muon.pt();
1233   double reliso_Puppi_withoutlep = val_PuppiWithoutLep / muon.pt();
1234   double reliso_Puppi_combined = mix_fraction * reliso_Puppi_withLep + (1.0 - mix_fraction) * reliso_Puppi_withoutlep;
1235   return reliso_Puppi_combined;
1236 }
1237 
1238 bool PATMuonProducer::isNeutralHadron(long pdgid) { return std::abs(pdgid) == 130; }
1239 
1240 bool PATMuonProducer::isChargedHadron(long pdgid) { return std::abs(pdgid) == 211; }
1241 
1242 bool PATMuonProducer::isPhoton(long pdgid) { return pdgid == 22; }
1243 
1244 // ParameterSet description for module
1245 void PATMuonProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
1246   edm::ParameterSetDescription iDesc;
1247   iDesc.setComment("PAT muon producer module");
1248 
1249   // input source
1250   iDesc.add<edm::InputTag>("muonSource", edm::InputTag("no default"))->setComment("input collection");
1251 
1252   // embedding
1253   iDesc.add<bool>("embedMuonBestTrack", true)->setComment("embed muon best track (global pflow)");
1254   iDesc.add<bool>("embedTunePMuonBestTrack", true)->setComment("embed muon best track (muon only)");
1255   iDesc.add<bool>("forceBestTrackEmbedding", true)
1256       ->setComment(
1257           "force embedding separately the best tracks even if they're already embedded e.g. as tracker or global "
1258           "tracks");
1259   iDesc.add<bool>("embedTrack", true)->setComment("embed external track");
1260   iDesc.add<bool>("embedStandAloneMuon", true)->setComment("embed external stand-alone muon");
1261   iDesc.add<bool>("embedCombinedMuon", false)->setComment("embed external combined muon");
1262   iDesc.add<bool>("embedPickyMuon", false)->setComment("embed external picky track");
1263   iDesc.add<bool>("embedTpfmsMuon", false)->setComment("embed external tpfms track");
1264   iDesc.add<bool>("embedDytMuon", false)->setComment("embed external dyt track ");
1265 
1266   // embedding of MET muon corrections
1267   iDesc.add<bool>("embedCaloMETMuonCorrs", true)->setComment("whether to add MET muon correction for caloMET or not");
1268   iDesc.add<edm::InputTag>("caloMETMuonCorrs", edm::InputTag("muonMETValueMapProducer", "muCorrData"))
1269       ->setComment("source of MET muon corrections for caloMET");
1270   iDesc.add<bool>("embedTcMETMuonCorrs", true)->setComment("whether to add MET muon correction for tcMET or not");
1271   iDesc.add<edm::InputTag>("tcMETMuonCorrs", edm::InputTag("muonTCMETValueMapProducer", "muCorrData"))
1272       ->setComment("source of MET muon corrections for tcMET");
1273 
1274   // pf specific parameters
1275   iDesc.add<edm::InputTag>("pfMuonSource", edm::InputTag("pfMuons"))->setComment("particle flow input collection");
1276   iDesc.add<bool>("useParticleFlow", false)->setComment("whether to use particle flow or not");
1277   iDesc.add<bool>("embedPFCandidate", false)->setComment("embed external particle flow object");
1278   iDesc.add<bool>("embedPfEcalEnergy", true)->setComment("add ecal energy as reconstructed by PF");
1279 
1280   // inverse beta computation
1281   iDesc.add<bool>("addInverseBeta", true)->setComment("add combined inverse beta");
1282   iDesc.add<edm::InputTag>("sourceInverseBeta", edm::InputTag("muons", "combined"))
1283       ->setComment("source of inverse beta values");
1284 
1285   // MC matching configurables
1286   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
1287   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
1288   std::vector<edm::InputTag> emptySourceVector;
1289   iDesc
1290       .addNode(edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
1291                edm::ParameterDescription<std::vector<edm::InputTag>>("genParticleMatch", emptySourceVector, true))
1292       ->setComment("input with MC match information");
1293 
1294   // mini-iso
1295   iDesc.add<bool>("computeMiniIso", false)->setComment("whether or not to compute and store electron mini-isolation");
1296   iDesc.add<bool>("computePuppiCombinedIso", false)
1297       ->setComment("whether or not to compute and store puppi combined isolation");
1298 
1299   iDesc.add<edm::InputTag>("pfCandsForMiniIso", edm::InputTag("packedPFCandidates"))
1300       ->setComment("collection to use to compute mini-iso");
1301   iDesc.add<std::vector<double>>("miniIsoParams", std::vector<double>())
1302       ->setComment("mini-iso parameters to use for muons");
1303 
1304   iDesc.add<bool>("addTriggerMatching", false)->setComment("add L1 and HLT matching to offline muon");
1305 
1306   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
1307 
1308   // IsoDeposit configurables
1309   edm::ParameterSetDescription isoDepositsPSet;
1310   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
1311   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
1312   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
1313   isoDepositsPSet.addOptional<edm::InputTag>("particle");
1314   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
1315   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
1316   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
1317   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
1318   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
1319   isoDepositsPSet.addOptional<std::vector<edm::InputTag>>("user");
1320   iDesc.addOptional("isoDeposits", isoDepositsPSet);
1321 
1322   // isolation values configurables
1323   edm::ParameterSetDescription isolationValuesPSet;
1324   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
1325   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
1326   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
1327   isolationValuesPSet.addOptional<edm::InputTag>("particle");
1328   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
1329   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
1330   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
1331   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
1332   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
1333   iDesc.addOptional("isolationValues", isolationValuesPSet);
1334 
1335   iDesc.ifValue(edm::ParameterDescription<bool>("addPuppiIsolation", false, true),
1336                 true >> (edm::ParameterDescription<edm::InputTag>(
1337                              "puppiIsolationChargedHadrons",
1338                              edm::InputTag("muonPUPPIIsolation", "h+-DR030-ThresholdVeto000-ConeVeto000"),
1339                              true) and
1340                          edm::ParameterDescription<edm::InputTag>(
1341                              "puppiIsolationNeutralHadrons",
1342                              edm::InputTag("muonPUPPIIsolation", "h0-DR030-ThresholdVeto000-ConeVeto001"),
1343                              true) and
1344                          edm::ParameterDescription<edm::InputTag>(
1345                              "puppiIsolationPhotons",
1346                              edm::InputTag("muonPUPPIIsolation", "gamma-DR030-ThresholdVeto000-ConeVeto001"),
1347                              true) and
1348                          edm::ParameterDescription<edm::InputTag>(
1349                              "puppiNoLeptonsIsolationChargedHadrons",
1350                              edm::InputTag("muonPUPPINoLeptonsIsolation", "h+-DR030-ThresholdVeto000-ConeVeto000"),
1351                              true) and
1352                          edm::ParameterDescription<edm::InputTag>(
1353                              "puppiNoLeptonsIsolationNeutralHadrons",
1354                              edm::InputTag("muonPUPPINoLeptonsIsolation", "h0-DR030-ThresholdVeto000-ConeVeto001"),
1355                              true) and
1356                          edm::ParameterDescription<edm::InputTag>(
1357                              "puppiNoLeptonsIsolationPhotons",
1358                              edm::InputTag("muonPUPPINoLeptonsIsolation", "gamma-DR030-ThresholdVeto000-ConeVeto001"),
1359                              true)) or
1360                     false >> edm::EmptyGroupDescription());
1361 
1362   // Efficiency configurables
1363   edm::ParameterSetDescription efficienciesPSet;
1364   efficienciesPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
1365   iDesc.add("efficiencies", efficienciesPSet);
1366   iDesc.add<bool>("addEfficiencies", false);
1367 
1368   // Check to see if the user wants to add user data
1369   edm::ParameterSetDescription userDataPSet;
1370   PATUserDataHelper<Muon>::fillDescription(userDataPSet);
1371   iDesc.addOptional("userData", userDataPSet);
1372 
1373   edm::ParameterSetDescription isolationPSet;
1374   isolationPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
1375   iDesc.add("userIsolation", isolationPSet);
1376 
1377   iDesc.add<bool>("embedHighLevelSelection", true)->setComment("embed high level selection");
1378   edm::ParameterSetDescription highLevelPSet;
1379   highLevelPSet.setAllowAnything();
1380   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true))
1381       ->setComment("input with high level selection");
1382   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("pvSrc", edm::InputTag(), true))
1383       ->setComment("input with high level selection");
1384 
1385   //descriptions.add("PATMuonProducer", iDesc);
1386 }
1387 
1388 // embed various impact parameters with errors
1389 // embed high level selection
1390 void PATMuonProducer::embedHighLevel(pat::Muon& aMuon,
1391                                      reco::TrackRef track,
1392                                      reco::TransientTrack& tt,
1393                                      reco::Vertex& primaryVertex,
1394                                      bool primaryVertexIsValid,
1395                                      reco::BeamSpot& beamspot,
1396                                      bool beamspotIsValid) {
1397   // Correct to PV
1398 
1399   // PV2D
1400   aMuon.setDB(track->dxy(primaryVertex.position()),
1401               track->dxyError(primaryVertex.position(), primaryVertex.covariance()),
1402               pat::Muon::PV2D);
1403 
1404   // PV3D
1405   std::pair<bool, Measurement1D> result =
1406       IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), primaryVertex);
1407   double d0_corr = result.second.value();
1408   double d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
1409   aMuon.setDB(d0_corr, d0_err, pat::Muon::PV3D);
1410 
1411   // Correct to beam spot
1412 
1413   // BS2D
1414   aMuon.setDB(track->dxy(beamspot), track->dxyError(beamspot), pat::Muon::BS2D);
1415 
1416   // make a fake vertex out of beam spot
1417   reco::Vertex vBeamspot(beamspot.position(), beamspot.rotatedCovariance3D());
1418 
1419   // BS3D
1420   result = IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), vBeamspot);
1421   d0_corr = result.second.value();
1422   d0_err = beamspotIsValid ? result.second.error() : -1.0;
1423   aMuon.setDB(d0_corr, d0_err, pat::Muon::BS3D);
1424 
1425   // PVDZ
1426   aMuon.setDB(
1427       track->dz(primaryVertex.position()), std::hypot(track->dzError(), primaryVertex.zError()), pat::Muon::PVDZ);
1428 }
1429 
1430 #include "FWCore/Framework/interface/MakerMacros.h"
1431 
1432 DEFINE_FWK_MODULE(PATMuonProducer);