Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-02-20 03:45:45

0001 /**
0002   \class    pat::PATElectronProducer PATElectronProducer.h "PhysicsTools/PatAlgos/interface/PATElectronProducer.h"
0003   \brief    Produces pat::Electron's
0004 
0005    The PATElectronProducer produces analysis-level pat::Electron's starting from
0006    a collection of objects of reco::GsfElectron.
0007 
0008   \author   Steven Lowette, James Lamb\
0009   \version  $Id: PATElectronProducer.h,v 1.31 2013/02/27 23:26:56 wmtan Exp $
0010 */
0011 
0012 #include "CommonTools/Egamma/interface/ConversionTools.h"
0013 #include "CommonTools/Utils/interface/PtComparator.h"
0014 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
0015 #include "DataFormats/Candidate/interface/CandAssociation.h"
0016 #include "DataFormats/Common/interface/Association.h"
0017 #include "DataFormats/Common/interface/ValueMap.h"
0018 #include "DataFormats/Common/interface/View.h"
0019 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
0020 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
0021 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
0022 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
0023 #include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
0024 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0025 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateFwd.h"
0026 #include "DataFormats/PatCandidates/interface/Electron.h"
0027 #include "DataFormats/PatCandidates/interface/PFIsolation.h"
0028 #include "DataFormats/PatCandidates/interface/UserData.h"
0029 #include "DataFormats/VertexReco/interface/Vertex.h"
0030 #include "FWCore/Framework/interface/Event.h"
0031 #include "FWCore/Framework/interface/stream/EDProducer.h"
0032 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0033 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0034 #include "FWCore/ParameterSet/interface/EmptyGroupDescription.h"
0035 #include "FWCore/ParameterSet/interface/FileInPath.h"
0036 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0037 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0038 #include "FWCore/Utilities/interface/InputTag.h"
0039 #include "FWCore/Utilities/interface/isFinite.h"
0040 #include "FWCore/Utilities/interface/transform.h"
0041 #include "Geometry/CaloTopology/interface/CaloSubdetectorTopology.h"
0042 #include "Geometry/CaloTopology/interface/CaloTopology.h"
0043 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0044 #include "Geometry/Records/interface/CaloTopologyRecord.h"
0045 #include "PhysicsTools/PatAlgos/interface/EfficiencyLoader.h"
0046 #include "PhysicsTools/PatAlgos/interface/KinResolutionsLoader.h"
0047 #include "PhysicsTools/PatAlgos/interface/MultiIsolator.h"
0048 #include "PhysicsTools/PatAlgos/interface/PATUserDataHelper.h"
0049 #include "PhysicsTools/PatUtils/interface/CaloIsolationEnergy.h"
0050 #include "PhysicsTools/PatUtils/interface/MiniIsolation.h"
0051 #include "PhysicsTools/PatUtils/interface/TrackerIsolationPt.h"
0052 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterLazyTools.h"
0053 #include "TrackingTools/IPTools/interface/IPTools.h"
0054 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
0055 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
0056 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
0057 
0058 #include <memory>
0059 #include <string>
0060 #include <vector>
0061 
0062 namespace pat {
0063 
0064   class TrackerIsolationPt;
0065   class CaloIsolationEnergy;
0066   class LeptonLRCalc;
0067 
0068   class PATElectronProducer : public edm::stream::EDProducer<> {
0069   public:
0070     explicit PATElectronProducer(const edm::ParameterSet& iConfig);
0071     ~PATElectronProducer() override;
0072 
0073     void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
0074 
0075     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0076 
0077   private:
0078     // configurables
0079     const edm::EDGetTokenT<edm::View<reco::GsfElectron>> electronToken_;
0080     const edm::EDGetTokenT<reco::ConversionCollection> hConversionsToken_;
0081     const bool embedGsfElectronCore_;
0082     const bool embedGsfTrack_;
0083     const bool embedSuperCluster_;
0084     const bool embedPflowSuperCluster_;
0085     const bool embedSeedCluster_;
0086     const bool embedBasicClusters_;
0087     const bool embedPreshowerClusters_;
0088     const bool embedPflowBasicClusters_;
0089     const bool embedPflowPreshowerClusters_;
0090     const bool embedTrack_;
0091     bool addGenMatch_;
0092     bool embedGenMatch_;
0093     const bool embedRecHits_;
0094     // for mini-iso calculation
0095     edm::EDGetTokenT<pat::PackedCandidateCollection> pcToken_;
0096     bool computeMiniIso_;
0097     std::vector<double> miniIsoParamsE_;
0098     std::vector<double> miniIsoParamsB_;
0099 
0100     typedef std::vector<edm::Handle<edm::Association<reco::GenParticleCollection>>> GenAssociations;
0101 
0102     std::vector<edm::EDGetTokenT<edm::Association<reco::GenParticleCollection>>> genMatchTokens_;
0103 
0104     /// pflow specific
0105     const bool useParticleFlow_;
0106     const bool usePfCandidateMultiMap_;
0107     const edm::EDGetTokenT<reco::PFCandidateCollection> pfElecToken_;
0108     const edm::EDGetTokenT<edm::ValueMap<reco::PFCandidatePtr>> pfCandidateMapToken_;
0109     const edm::EDGetTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>> pfCandidateMultiMapToken_;
0110     const bool embedPFCandidate_;
0111 
0112     /// mva input variables
0113     const bool addMVAVariables_;
0114     const edm::InputTag reducedBarrelRecHitCollection_;
0115     const edm::EDGetTokenT<EcalRecHitCollection> reducedBarrelRecHitCollectionToken_;
0116     const edm::InputTag reducedEndcapRecHitCollection_;
0117     const edm::EDGetTokenT<EcalRecHitCollection> reducedEndcapRecHitCollectionToken_;
0118     const EcalClusterLazyTools::ESGetTokens ecalClusterToolsESGetTokens_;
0119 
0120     const bool addPFClusterIso_;
0121     const bool addPuppiIsolation_;
0122     const edm::EDGetTokenT<edm::ValueMap<float>> ecalPFClusterIsoT_;
0123     const edm::EDGetTokenT<edm::ValueMap<float>> hcalPFClusterIsoT_;
0124 
0125     /// embed high level selection variables?
0126     const bool embedHighLevelSelection_;
0127     const edm::EDGetTokenT<reco::BeamSpot> beamLineToken_;
0128     const edm::EDGetTokenT<std::vector<reco::Vertex>> pvToken_;
0129 
0130     typedef edm::RefToBase<reco::GsfElectron> ElectronBaseRef;
0131     typedef std::vector<edm::Handle<edm::ValueMap<IsoDeposit>>> IsoDepositMaps;
0132     typedef std::vector<edm::Handle<edm::ValueMap<double>>> IsolationValueMaps;
0133 
0134     /// common electron filling, for both the standard and PF2PAT case
0135     void fillElectron(Electron& aElectron,
0136                       const ElectronBaseRef& electronRef,
0137                       const reco::CandidateBaseRef& baseRef,
0138                       const GenAssociations& genMatches,
0139                       const IsoDepositMaps& deposits,
0140                       const bool pfId,
0141                       const IsolationValueMaps& isolationValues,
0142                       const IsolationValueMaps& isolationValuesNoPFId) const;
0143 
0144     void fillElectron2(Electron& anElectron,
0145                        const reco::CandidatePtr& candPtrForIsolation,
0146                        const reco::CandidatePtr& candPtrForGenMatch,
0147                        const reco::CandidatePtr& candPtrForLoader,
0148                        const GenAssociations& genMatches,
0149                        const IsoDepositMaps& deposits,
0150                        const IsolationValueMaps& isolationValues) const;
0151 
0152     // set the mini-isolation variables
0153     void setElectronMiniIso(pat::Electron& anElectron, const pat::PackedCandidateCollection* pc);
0154 
0155     // embed various impact parameters with errors
0156     // embed high level selection
0157     void embedHighLevel(pat::Electron& anElectron,
0158                         reco::GsfTrackRef track,
0159                         reco::TransientTrack& tt,
0160                         reco::Vertex& primaryVertex,
0161                         bool primaryVertexIsValid,
0162                         reco::BeamSpot& beamspot,
0163                         bool beamspotIsValid);
0164 
0165     typedef std::pair<pat::IsolationKeys, edm::InputTag> IsolationLabel;
0166     typedef std::vector<IsolationLabel> IsolationLabels;
0167 
0168     /// fill the labels vector from the contents of the parameter set,
0169     /// for the isodeposit or isolation values embedding
0170     template <typename T>
0171     void readIsolationLabels(const edm::ParameterSet& iConfig,
0172                              const char* psetName,
0173                              IsolationLabels& labels,
0174                              std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens);
0175 
0176     const bool addElecID_;
0177     typedef std::pair<std::string, edm::InputTag> NameTag;
0178     std::vector<NameTag> elecIDSrcs_;
0179     std::vector<edm::EDGetTokenT<edm::ValueMap<float>>> elecIDTokens_;
0180 
0181     // tools
0182     const GreaterByPt<Electron> pTComparator_;
0183 
0184     pat::helper::MultiIsolator isolator_;
0185     pat::helper::MultiIsolator::IsolationValuePairs isolatorTmpStorage_;  // better here than recreate at each event
0186     IsolationLabels isoDepositLabels_;
0187     std::vector<edm::EDGetTokenT<edm::ValueMap<IsoDeposit>>> isoDepositTokens_;
0188     IsolationLabels isolationValueLabels_;
0189     std::vector<edm::EDGetTokenT<edm::ValueMap<double>>> isolationValueTokens_;
0190     IsolationLabels isolationValueLabelsNoPFId_;
0191     std::vector<edm::EDGetTokenT<edm::ValueMap<double>>> isolationValueNoPFIdTokens_;
0192 
0193     const bool addEfficiencies_;
0194     pat::helper::EfficiencyLoader efficiencyLoader_;
0195 
0196     const bool addResolutions_;
0197     pat::helper::KinResolutionsLoader resolutionLoader_;
0198 
0199     const bool useUserData_;
0200     //PUPPI isolation tokens
0201     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons_;
0202     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons_;
0203     edm::EDGetTokenT<edm::ValueMap<float>> PUPPIIsolation_photons_;
0204     //PUPPINoLeptons isolation tokens
0205     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_charged_hadrons_;
0206     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_neutral_hadrons_;
0207     edm::EDGetTokenT<edm::ValueMap<float>> PUPPINoLeptonsIsolation_photons_;
0208     pat::PATUserDataHelper<pat::Electron> userDataHelper_;
0209 
0210     const edm::ESGetToken<CaloTopology, CaloTopologyRecord> ecalTopologyToken_;
0211     const edm::ESGetToken<TransientTrackBuilder, TransientTrackRecord> trackBuilderToken_;
0212 
0213     const CaloTopology* ecalTopology_;
0214   };
0215 }  // namespace pat
0216 
0217 template <typename T>
0218 void pat::PATElectronProducer::readIsolationLabels(const edm::ParameterSet& iConfig,
0219                                                    const char* psetName,
0220                                                    pat::PATElectronProducer::IsolationLabels& labels,
0221                                                    std::vector<edm::EDGetTokenT<edm::ValueMap<T>>>& tokens) {
0222   labels.clear();
0223 
0224   if (iConfig.exists(psetName)) {
0225     edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>(psetName);
0226 
0227     if (depconf.exists("tracker"))
0228       labels.push_back(std::make_pair(pat::TrackIso, depconf.getParameter<edm::InputTag>("tracker")));
0229     if (depconf.exists("ecal"))
0230       labels.push_back(std::make_pair(pat::EcalIso, depconf.getParameter<edm::InputTag>("ecal")));
0231     if (depconf.exists("hcal"))
0232       labels.push_back(std::make_pair(pat::HcalIso, depconf.getParameter<edm::InputTag>("hcal")));
0233     if (depconf.exists("pfAllParticles")) {
0234       labels.push_back(std::make_pair(pat::PfAllParticleIso, depconf.getParameter<edm::InputTag>("pfAllParticles")));
0235     }
0236     if (depconf.exists("pfChargedHadrons")) {
0237       labels.push_back(
0238           std::make_pair(pat::PfChargedHadronIso, depconf.getParameter<edm::InputTag>("pfChargedHadrons")));
0239     }
0240     if (depconf.exists("pfChargedAll")) {
0241       labels.push_back(std::make_pair(pat::PfChargedAllIso, depconf.getParameter<edm::InputTag>("pfChargedAll")));
0242     }
0243     if (depconf.exists("pfPUChargedHadrons")) {
0244       labels.push_back(
0245           std::make_pair(pat::PfPUChargedHadronIso, depconf.getParameter<edm::InputTag>("pfPUChargedHadrons")));
0246     }
0247     if (depconf.exists("pfNeutralHadrons")) {
0248       labels.push_back(
0249           std::make_pair(pat::PfNeutralHadronIso, depconf.getParameter<edm::InputTag>("pfNeutralHadrons")));
0250     }
0251     if (depconf.exists("pfPhotons")) {
0252       labels.push_back(std::make_pair(pat::PfGammaIso, depconf.getParameter<edm::InputTag>("pfPhotons")));
0253     }
0254     if (depconf.exists("user")) {
0255       std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag>>("user");
0256       std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
0257       int key = pat::IsolationKeys::UserBaseIso;
0258       for (; it != ed; ++it, ++key) {
0259         labels.push_back(std::make_pair(pat::IsolationKeys(key), *it));
0260       }
0261     }
0262   }
0263   tokens = edm::vector_transform(
0264       labels, [this](IsolationLabel const& label) { return consumes<edm::ValueMap<T>>(label.second); });
0265 }
0266 
0267 using namespace pat;
0268 using namespace std;
0269 
0270 PATElectronProducer::PATElectronProducer(const edm::ParameterSet& iConfig)
0271     :  // general configurables
0272       electronToken_(consumes<edm::View<reco::GsfElectron>>(iConfig.getParameter<edm::InputTag>("electronSource"))),
0273       hConversionsToken_(consumes<reco::ConversionCollection>(edm::InputTag("allConversions"))),
0274       embedGsfElectronCore_(iConfig.getParameter<bool>("embedGsfElectronCore")),
0275       embedGsfTrack_(iConfig.getParameter<bool>("embedGsfTrack")),
0276       embedSuperCluster_(iConfig.getParameter<bool>("embedSuperCluster")),
0277       embedPflowSuperCluster_(iConfig.getParameter<bool>("embedPflowSuperCluster")),
0278       embedSeedCluster_(iConfig.getParameter<bool>("embedSeedCluster")),
0279       embedBasicClusters_(iConfig.getParameter<bool>("embedBasicClusters")),
0280       embedPreshowerClusters_(iConfig.getParameter<bool>("embedPreshowerClusters")),
0281       embedPflowBasicClusters_(iConfig.getParameter<bool>("embedPflowBasicClusters")),
0282       embedPflowPreshowerClusters_(iConfig.getParameter<bool>("embedPflowPreshowerClusters")),
0283       embedTrack_(iConfig.getParameter<bool>("embedTrack")),
0284       addGenMatch_(iConfig.getParameter<bool>("addGenMatch")),
0285       embedGenMatch_(addGenMatch_ ? iConfig.getParameter<bool>("embedGenMatch") : false),
0286       embedRecHits_(iConfig.getParameter<bool>("embedRecHits")),
0287       // pflow configurables
0288       useParticleFlow_(iConfig.getParameter<bool>("useParticleFlow")),
0289       usePfCandidateMultiMap_(iConfig.getParameter<bool>("usePfCandidateMultiMap")),
0290       pfElecToken_(!usePfCandidateMultiMap_
0291                        ? consumes<reco::PFCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfElectronSource"))
0292                        : edm::EDGetTokenT<reco::PFCandidateCollection>()),
0293       pfCandidateMapToken_(!usePfCandidateMultiMap_ ? mayConsume<edm::ValueMap<reco::PFCandidatePtr>>(
0294                                                           iConfig.getParameter<edm::InputTag>("pfCandidateMap"))
0295                                                     : edm::EDGetTokenT<edm::ValueMap<reco::PFCandidatePtr>>()),
0296       pfCandidateMultiMapToken_(usePfCandidateMultiMap_
0297                                     ? consumes<edm::ValueMap<std::vector<reco::PFCandidateRef>>>(
0298                                           iConfig.getParameter<edm::InputTag>("pfCandidateMultiMap"))
0299                                     : edm::EDGetTokenT<edm::ValueMap<std::vector<reco::PFCandidateRef>>>()),
0300       embedPFCandidate_(iConfig.getParameter<bool>("embedPFCandidate")),
0301       // mva input variables
0302       addMVAVariables_(iConfig.getParameter<bool>("addMVAVariables")),
0303       reducedBarrelRecHitCollection_(iConfig.getParameter<edm::InputTag>("reducedBarrelRecHitCollection")),
0304       reducedBarrelRecHitCollectionToken_(mayConsume<EcalRecHitCollection>(reducedBarrelRecHitCollection_)),
0305       reducedEndcapRecHitCollection_(iConfig.getParameter<edm::InputTag>("reducedEndcapRecHitCollection")),
0306       reducedEndcapRecHitCollectionToken_(mayConsume<EcalRecHitCollection>(reducedEndcapRecHitCollection_)),
0307       ecalClusterToolsESGetTokens_{consumesCollector()},
0308       // PFCluster Isolation maps
0309       addPFClusterIso_(iConfig.getParameter<bool>("addPFClusterIso")),
0310       addPuppiIsolation_(iConfig.getParameter<bool>("addPuppiIsolation")),
0311       ecalPFClusterIsoT_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("ecalPFClusterIsoMap"))),
0312       hcalPFClusterIsoT_(consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("hcalPFClusterIsoMap"))),
0313       // embed high level selection variables?
0314       embedHighLevelSelection_(iConfig.getParameter<bool>("embedHighLevelSelection")),
0315       beamLineToken_(consumes<reco::BeamSpot>(iConfig.getParameter<edm::InputTag>("beamLineSrc"))),
0316       pvToken_(mayConsume<std::vector<reco::Vertex>>(iConfig.getParameter<edm::InputTag>("pvSrc"))),
0317       addElecID_(iConfig.getParameter<bool>("addElectronID")),
0318       pTComparator_(),
0319       isolator_(iConfig.getParameter<edm::ParameterSet>("userIsolation"), consumesCollector(), false),
0320       addEfficiencies_(iConfig.getParameter<bool>("addEfficiencies")),
0321       addResolutions_(iConfig.getParameter<bool>("addResolutions")),
0322       useUserData_(iConfig.exists("userData")),
0323       ecalTopologyToken_{esConsumes()},
0324       trackBuilderToken_{esConsumes(edm::ESInputTag("", "TransientTrackBuilder"))} {
0325   // MC matching configurables (scheduled mode)
0326 
0327   if (addGenMatch_) {
0328     genMatchTokens_.push_back(consumes<edm::Association<reco::GenParticleCollection>>(
0329         iConfig.getParameter<edm::InputTag>("genParticleMatch")));
0330   }
0331   // resolution configurables
0332   if (addResolutions_) {
0333     resolutionLoader_ =
0334         pat::helper::KinResolutionsLoader(iConfig.getParameter<edm::ParameterSet>("resolutions"), consumesCollector());
0335   }
0336   if (addPuppiIsolation_) {
0337     //puppi
0338     PUPPIIsolation_charged_hadrons_ =
0339         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationChargedHadrons"));
0340     PUPPIIsolation_neutral_hadrons_ =
0341         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationNeutralHadrons"));
0342     PUPPIIsolation_photons_ =
0343         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiIsolationPhotons"));
0344     //puppiNoLeptons
0345     PUPPINoLeptonsIsolation_charged_hadrons_ =
0346         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationChargedHadrons"));
0347     PUPPINoLeptonsIsolation_neutral_hadrons_ =
0348         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationNeutralHadrons"));
0349     PUPPINoLeptonsIsolation_photons_ =
0350         consumes<edm::ValueMap<float>>(iConfig.getParameter<edm::InputTag>("puppiNoLeptonsIsolationPhotons"));
0351   }
0352   // electron ID configurables
0353   if (addElecID_) {
0354     // it might be a single electron ID
0355     if (iConfig.existsAs<edm::InputTag>("electronIDSource")) {
0356       elecIDSrcs_.push_back(NameTag("", iConfig.getParameter<edm::InputTag>("electronIDSource")));
0357     }
0358     // or there might be many of them
0359     if (iConfig.existsAs<edm::ParameterSet>("electronIDSources")) {
0360       // please don't configure me twice
0361       if (!elecIDSrcs_.empty()) {
0362         throw cms::Exception("Configuration")
0363             << "PATElectronProducer: you can't specify both 'electronIDSource' and 'electronIDSources'\n";
0364       }
0365       // read the different electron ID names
0366       edm::ParameterSet idps = iConfig.getParameter<edm::ParameterSet>("electronIDSources");
0367       std::vector<std::string> names = idps.getParameterNamesForType<edm::InputTag>();
0368       for (std::vector<std::string>::const_iterator it = names.begin(), ed = names.end(); it != ed; ++it) {
0369         elecIDSrcs_.push_back(NameTag(*it, idps.getParameter<edm::InputTag>(*it)));
0370       }
0371     }
0372     // but in any case at least once
0373     if (elecIDSrcs_.empty()) {
0374       throw cms::Exception("Configuration")
0375           << "PATElectronProducer: id addElectronID is true, you must specify either:\n"
0376           << "\tInputTag electronIDSource = <someTag>\n"
0377           << "or\n"
0378           << "\tPSet electronIDSources = { \n"
0379           << "\t\tInputTag <someName> = <someTag>   // as many as you want \n "
0380           << "\t}\n";
0381     }
0382   }
0383   elecIDTokens_ = edm::vector_transform(
0384       elecIDSrcs_, [this](NameTag const& tag) { return mayConsume<edm::ValueMap<float>>(tag.second); });
0385   // construct resolution calculator
0386 
0387   //   // IsoDeposit configurables
0388   //   if (iConfig.exists("isoDeposits")) {
0389   //      edm::ParameterSet depconf = iConfig.getParameter<edm::ParameterSet>("isoDeposits");
0390   //      if (depconf.exists("tracker")) isoDepositLabels_.push_back(std::make_pair(TrackerIso, depconf.getParameter<edm::InputTag>("tracker")));
0391   //      if (depconf.exists("ecal"))    isoDepositLabels_.push_back(std::make_pair(ECalIso, depconf.getParameter<edm::InputTag>("ecal")));
0392   //      if (depconf.exists("hcal"))    isoDepositLabels_.push_back(std::make_pair(HCalIso, depconf.getParameter<edm::InputTag>("hcal")));
0393 
0394   //      if (depconf.exists("user")) {
0395   //         std::vector<edm::InputTag> userdeps = depconf.getParameter<std::vector<edm::InputTag> >("user");
0396   //         std::vector<edm::InputTag>::const_iterator it = userdeps.begin(), ed = userdeps.end();
0397   //         int key = UserBaseIso;
0398   //         for ( ; it != ed; ++it, ++key) {
0399   //             isoDepositLabels_.push_back(std::make_pair(IsolationKeys(key), *it));
0400   //         }
0401   //      }
0402   //   }
0403   //   isoDepositTokens_ = edm::vector_transform(isoDepositLabels_, [this](std::pair<IsolationKeys,edm::InputTag> const & label){return consumes<edm::ValueMap<IsoDeposit> >(label.second);});
0404 
0405   // for mini-iso
0406   computeMiniIso_ = iConfig.getParameter<bool>("computeMiniIso");
0407   miniIsoParamsE_ = iConfig.getParameter<std::vector<double>>("miniIsoParamsE");
0408   miniIsoParamsB_ = iConfig.getParameter<std::vector<double>>("miniIsoParamsB");
0409   if (computeMiniIso_ && (miniIsoParamsE_.size() != 9 || miniIsoParamsB_.size() != 9)) {
0410     throw cms::Exception("ParameterError") << "miniIsoParams must have exactly 9 elements.\n";
0411   }
0412   if (computeMiniIso_)
0413     pcToken_ = consumes<pat::PackedCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfCandsForMiniIso"));
0414 
0415   // read isoDeposit labels, for direct embedding
0416   readIsolationLabels(iConfig, "isoDeposits", isoDepositLabels_, isoDepositTokens_);
0417   // read isolation value labels, for direct embedding
0418   readIsolationLabels(iConfig, "isolationValues", isolationValueLabels_, isolationValueTokens_);
0419   // read isolation value labels for non PF identified electron, for direct embedding
0420   readIsolationLabels(iConfig, "isolationValuesNoPFId", isolationValueLabelsNoPFId_, isolationValueNoPFIdTokens_);
0421   // Efficiency configurables
0422   if (addEfficiencies_) {
0423     efficiencyLoader_ =
0424         pat::helper::EfficiencyLoader(iConfig.getParameter<edm::ParameterSet>("efficiencies"), consumesCollector());
0425   }
0426   // Check to see if the user wants to add user data
0427   if (useUserData_) {
0428     userDataHelper_ =
0429         PATUserDataHelper<Electron>(iConfig.getParameter<edm::ParameterSet>("userData"), consumesCollector());
0430   }
0431 
0432   // consistency check
0433   if (useParticleFlow_ && usePfCandidateMultiMap_)
0434     throw cms::Exception("Configuration", "usePfCandidateMultiMap not supported when useParticleFlow is set to true");
0435 
0436   // produces vector of muons
0437   produces<std::vector<Electron>>();
0438 }
0439 
0440 PATElectronProducer::~PATElectronProducer() {}
0441 
0442 void PATElectronProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0443   // switch off embedding (in unschedules mode)
0444   if (iEvent.isRealData()) {
0445     addGenMatch_ = false;
0446     embedGenMatch_ = false;
0447   }
0448 
0449   ecalTopology_ = &iSetup.getData(ecalTopologyToken_);
0450 
0451   // Get the collection of electrons from the event
0452   edm::Handle<edm::View<reco::GsfElectron>> electrons;
0453   iEvent.getByToken(electronToken_, electrons);
0454 
0455   edm::Handle<PackedCandidateCollection> pc;
0456   if (computeMiniIso_)
0457     iEvent.getByToken(pcToken_, pc);
0458 
0459   // for additional mva variables
0460   edm::InputTag reducedEBRecHitCollection(string("reducedEcalRecHitsEB"));
0461   edm::InputTag reducedEERecHitCollection(string("reducedEcalRecHitsEE"));
0462   //EcalClusterLazyTools lazyTools(iEvent, iSetup, reducedEBRecHitCollection, reducedEERecHitCollection);
0463   EcalClusterLazyTools lazyTools(iEvent,
0464                                  ecalClusterToolsESGetTokens_.get(iSetup),
0465                                  reducedBarrelRecHitCollectionToken_,
0466                                  reducedEndcapRecHitCollectionToken_);
0467 
0468   // for conversion veto selection
0469   edm::Handle<reco::ConversionCollection> hConversions;
0470   iEvent.getByToken(hConversionsToken_, hConversions);
0471 
0472   // Get the ESHandle for the transient track builder, if needed for
0473   // high level selection embedding
0474   edm::ESHandle<TransientTrackBuilder> trackBuilder;
0475 
0476   if (isolator_.enabled())
0477     isolator_.beginEvent(iEvent, iSetup);
0478 
0479   if (efficiencyLoader_.enabled())
0480     efficiencyLoader_.newEvent(iEvent);
0481   if (resolutionLoader_.enabled())
0482     resolutionLoader_.newEvent(iEvent, iSetup);
0483 
0484   IsoDepositMaps deposits(isoDepositTokens_.size());
0485   for (size_t j = 0, nd = isoDepositTokens_.size(); j < nd; ++j) {
0486     iEvent.getByToken(isoDepositTokens_[j], deposits[j]);
0487   }
0488 
0489   IsolationValueMaps isolationValues(isolationValueTokens_.size());
0490   for (size_t j = 0; j < isolationValueTokens_.size(); ++j) {
0491     iEvent.getByToken(isolationValueTokens_[j], isolationValues[j]);
0492   }
0493 
0494   IsolationValueMaps isolationValuesNoPFId(isolationValueNoPFIdTokens_.size());
0495   for (size_t j = 0; j < isolationValueNoPFIdTokens_.size(); ++j) {
0496     iEvent.getByToken(isolationValueNoPFIdTokens_[j], isolationValuesNoPFId[j]);
0497   }
0498 
0499   // prepare the MC matching
0500   GenAssociations genMatches(genMatchTokens_.size());
0501   if (addGenMatch_) {
0502     for (size_t j = 0, nd = genMatchTokens_.size(); j < nd; ++j) {
0503       iEvent.getByToken(genMatchTokens_[j], genMatches[j]);
0504     }
0505   }
0506 
0507   // prepare ID extraction
0508   std::vector<edm::Handle<edm::ValueMap<float>>> idhandles;
0509   std::vector<pat::Electron::IdPair> ids;
0510   if (addElecID_) {
0511     idhandles.resize(elecIDSrcs_.size());
0512     ids.resize(elecIDSrcs_.size());
0513     for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
0514       iEvent.getByToken(elecIDTokens_[i], idhandles[i]);
0515       ids[i].first = elecIDSrcs_[i].first;
0516     }
0517   }
0518 
0519   // prepare the high level selection:
0520   // needs beamline
0521   reco::TrackBase::Point beamPoint(0, 0, 0);
0522   reco::Vertex primaryVertex;
0523   reco::BeamSpot beamSpot;
0524   bool beamSpotIsValid = false;
0525   bool primaryVertexIsValid = false;
0526 
0527   // Get the beamspot
0528   edm::Handle<reco::BeamSpot> beamSpotHandle;
0529   iEvent.getByToken(beamLineToken_, beamSpotHandle);
0530 
0531   if (embedHighLevelSelection_) {
0532     // Get the primary vertex
0533     edm::Handle<std::vector<reco::Vertex>> pvHandle;
0534     iEvent.getByToken(pvToken_, pvHandle);
0535 
0536     // This is needed by the IPTools methods from the tracking group
0537     trackBuilder = iSetup.getHandle(trackBuilderToken_);
0538 
0539     if (beamSpotHandle.isValid()) {
0540       beamSpot = *beamSpotHandle;
0541       beamSpotIsValid = true;
0542     } else {
0543       edm::LogError("DataNotAvailable") << "No beam spot available from EventSetup, not adding high level selection \n";
0544     }
0545 
0546     if (pvHandle.isValid() && !pvHandle->empty()) {
0547       primaryVertex = pvHandle->at(0);
0548       primaryVertexIsValid = true;
0549     } else {
0550       edm::LogError("DataNotAvailable")
0551           << "No primary vertex available from EventSetup, not adding high level selection \n";
0552     }
0553   }
0554   //value maps for puppi isolation
0555   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_charged_hadrons;
0556   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_neutral_hadrons;
0557   edm::Handle<edm::ValueMap<float>> PUPPIIsolation_photons;
0558   //value maps for puppiNoLeptons isolation
0559   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_charged_hadrons;
0560   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_neutral_hadrons;
0561   edm::Handle<edm::ValueMap<float>> PUPPINoLeptonsIsolation_photons;
0562   if (addPuppiIsolation_) {
0563     //puppi
0564     iEvent.getByToken(PUPPIIsolation_charged_hadrons_, PUPPIIsolation_charged_hadrons);
0565     iEvent.getByToken(PUPPIIsolation_neutral_hadrons_, PUPPIIsolation_neutral_hadrons);
0566     iEvent.getByToken(PUPPIIsolation_photons_, PUPPIIsolation_photons);
0567     //puppiNoLeptons
0568     iEvent.getByToken(PUPPINoLeptonsIsolation_charged_hadrons_, PUPPINoLeptonsIsolation_charged_hadrons);
0569     iEvent.getByToken(PUPPINoLeptonsIsolation_neutral_hadrons_, PUPPINoLeptonsIsolation_neutral_hadrons);
0570     iEvent.getByToken(PUPPINoLeptonsIsolation_photons_, PUPPINoLeptonsIsolation_photons);
0571   }
0572 
0573   std::vector<Electron>* patElectrons = new std::vector<Electron>();
0574 
0575   if (useParticleFlow_) {
0576     edm::Handle<reco::PFCandidateCollection> pfElectrons;
0577     iEvent.getByToken(pfElecToken_, pfElectrons);
0578     unsigned index = 0;
0579 
0580     for (reco::PFCandidateConstIterator i = pfElectrons->begin(); i != pfElectrons->end(); ++i, ++index) {
0581       reco::PFCandidateRef pfRef(pfElectrons, index);
0582       reco::PFCandidatePtr ptrToPFElectron(pfElectrons, index);
0583       //       reco::CandidateBaseRef pfBaseRef( pfRef );
0584 
0585       reco::GsfTrackRef PfTk = i->gsfTrackRef();
0586 
0587       bool Matched = false;
0588       bool MatchedToAmbiguousGsfTrack = false;
0589       for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end();
0590            ++itElectron) {
0591         unsigned int idx = itElectron - electrons->begin();
0592         auto elePtr = electrons->ptrAt(idx);
0593         if (Matched || MatchedToAmbiguousGsfTrack)
0594           continue;
0595 
0596         reco::GsfTrackRef EgTk = itElectron->gsfTrack();
0597 
0598         if (itElectron->gsfTrack() == i->gsfTrackRef()) {
0599           Matched = true;
0600         } else {
0601           for (auto const& it : itElectron->ambiguousGsfTracks()) {
0602             MatchedToAmbiguousGsfTrack |= (bool)(i->gsfTrackRef() == it);
0603           }
0604         }
0605 
0606         if (Matched || MatchedToAmbiguousGsfTrack) {
0607           // ptr needed for finding the matched gen particle
0608           reco::CandidatePtr ptrToGsfElectron(electrons, idx);
0609 
0610           // ref to base needed for the construction of the pat object
0611           const edm::RefToBase<reco::GsfElectron>& elecsRef = electrons->refAt(idx);
0612           Electron anElectron(elecsRef);
0613           anElectron.setPFCandidateRef(pfRef);
0614           if (addPuppiIsolation_) {
0615             anElectron.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[elePtr],
0616                                          (*PUPPIIsolation_neutral_hadrons)[elePtr],
0617                                          (*PUPPIIsolation_photons)[elePtr]);
0618             anElectron.setIsolationPUPPINoLeptons((*PUPPINoLeptonsIsolation_charged_hadrons)[elePtr],
0619                                                   (*PUPPINoLeptonsIsolation_neutral_hadrons)[elePtr],
0620                                                   (*PUPPINoLeptonsIsolation_photons)[elePtr]);
0621           } else {
0622             anElectron.setIsolationPUPPI(-999., -999., -999.);
0623             anElectron.setIsolationPUPPINoLeptons(-999., -999., -999.);
0624           }
0625 
0626           //it should be always true when particleFlow electrons are used.
0627           anElectron.setIsPF(true);
0628 
0629           if (embedPFCandidate_)
0630             anElectron.embedPFCandidate();
0631 
0632           if (useUserData_) {
0633             userDataHelper_.add(anElectron, iEvent, iSetup);
0634           }
0635 
0636           double ip3d = -999;  // for mva variable
0637 
0638           // embed high level selection
0639           if (embedHighLevelSelection_) {
0640             // get the global track
0641             const reco::GsfTrackRef& track = PfTk;
0642 
0643             // Make sure the collection it points to is there
0644             if (track.isNonnull() && track.isAvailable()) {
0645               reco::TransientTrack tt = trackBuilder->build(track);
0646               embedHighLevel(anElectron, track, tt, primaryVertex, primaryVertexIsValid, beamSpot, beamSpotIsValid);
0647 
0648               std::pair<bool, Measurement1D> ip3dpv = IPTools::absoluteImpactParameter3D(tt, primaryVertex);
0649               ip3d = ip3dpv.second.value();  // for mva variable
0650             }
0651           }
0652 
0653           //Electron Id
0654 
0655           if (addElecID_) {
0656             //STANDARD EL ID
0657             for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
0658               ids[i].second = (*idhandles[i])[elecsRef];
0659             }
0660             //SPECIFIC PF ID
0661             ids.push_back(std::make_pair("pf_evspi", pfRef->mva_e_pi()));
0662             ids.push_back(std::make_pair("pf_evsmu", pfRef->mva_e_mu()));
0663             anElectron.setElectronIDs(ids);
0664           }
0665 
0666           if (addMVAVariables_) {
0667             // add missing mva variables
0668             const auto& vCov = lazyTools.localCovariances(*(itElectron->superCluster()->seed()));
0669             anElectron.setMvaVariables(vCov[1], ip3d);
0670           }
0671           // PFClusterIso
0672           if (addPFClusterIso_) {
0673             // Get PFCluster Isolation
0674             edm::Handle<edm::ValueMap<float>> ecalPFClusterIsoMapH;
0675             iEvent.getByToken(ecalPFClusterIsoT_, ecalPFClusterIsoMapH);
0676             edm::Handle<edm::ValueMap<float>> hcalPFClusterIsoMapH;
0677             iEvent.getByToken(hcalPFClusterIsoT_, hcalPFClusterIsoMapH);
0678             reco::GsfElectron::PflowIsolationVariables newPFIsol = anElectron.pfIsolationVariables();
0679             newPFIsol.sumEcalClusterEt = (*ecalPFClusterIsoMapH)[elecsRef];
0680             newPFIsol.sumHcalClusterEt = (*hcalPFClusterIsoMapH)[elecsRef];
0681             anElectron.setPfIsolationVariables(newPFIsol);
0682           }
0683 
0684           std::vector<DetId> selectedCells;
0685           bool barrel = itElectron->isEB();
0686           //loop over sub clusters
0687           if (embedBasicClusters_) {
0688             for (reco::CaloCluster_iterator clusIt = itElectron->superCluster()->clustersBegin();
0689                  clusIt != itElectron->superCluster()->clustersEnd();
0690                  ++clusIt) {
0691               //get seed (max energy xtal)
0692               DetId seed = lazyTools.getMaximum(**clusIt).first;
0693               //get all xtals in 5x5 window around the seed
0694               std::vector<DetId> dets5x5 =
0695                   (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0696                            : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0697               selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0698 
0699               //get all xtals belonging to cluster
0700               for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0701                 selectedCells.push_back(hit.first);
0702               }
0703             }
0704           }
0705 
0706           if (embedPflowBasicClusters_ && itElectron->parentSuperCluster().isNonnull()) {
0707             for (reco::CaloCluster_iterator clusIt = itElectron->parentSuperCluster()->clustersBegin();
0708                  clusIt != itElectron->parentSuperCluster()->clustersEnd();
0709                  ++clusIt) {
0710               //get seed (max energy xtal)
0711               DetId seed = lazyTools.getMaximum(**clusIt).first;
0712               //get all xtals in 5x5 window around the seed
0713               std::vector<DetId> dets5x5 =
0714                   (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0715                            : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0716               selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0717 
0718               //get all xtals belonging to cluster
0719               for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0720                 selectedCells.push_back(hit.first);
0721               }
0722             }
0723           }
0724 
0725           //remove duplicates
0726           std::sort(selectedCells.begin(), selectedCells.end());
0727           auto last = std::unique(selectedCells.begin(), selectedCells.end());
0728           selectedCells.erase(last, selectedCells.end());
0729 
0730           // Retrieve the corresponding RecHits
0731 
0732           edm::Handle<EcalRecHitCollection> rechitsH;
0733           if (barrel)
0734             iEvent.getByToken(reducedBarrelRecHitCollectionToken_, rechitsH);
0735           else
0736             iEvent.getByToken(reducedEndcapRecHitCollectionToken_, rechitsH);
0737 
0738           EcalRecHitCollection selectedRecHits;
0739           const EcalRecHitCollection* recHits = rechitsH.product();
0740 
0741           unsigned nSelectedCells = selectedCells.size();
0742           for (unsigned icell = 0; icell < nSelectedCells; ++icell) {
0743             EcalRecHitCollection::const_iterator it = recHits->find(selectedCells[icell]);
0744             if (it != recHits->end()) {
0745               selectedRecHits.push_back(*it);
0746             }
0747           }
0748           selectedRecHits.sort();
0749           if (embedRecHits_)
0750             anElectron.embedRecHits(&selectedRecHits);
0751 
0752           // set conversion veto selection
0753           bool passconversionveto = false;
0754           if (hConversions.isValid()) {
0755             // this is recommended method
0756             passconversionveto =
0757                 !ConversionTools::hasMatchedConversion(*itElectron, *hConversions, beamSpotHandle->position());
0758           } else {
0759             // use missing hits without vertex fit method
0760             passconversionveto =
0761                 itElectron->gsfTrack()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) < 1;
0762           }
0763 
0764           anElectron.setPassConversionVeto(passconversionveto);
0765 
0766           //      fillElectron(anElectron,elecsRef,pfBaseRef,
0767           //               genMatches, deposits, isolationValues);
0768 
0769           //COLIN small warning !
0770           // we are currently choosing to take the 4-momentum of the PFCandidate;
0771           // the momentum of the GsfElectron is saved though
0772           // we must therefore match the GsfElectron.
0773           // because of this, we should not change the source of the electron matcher
0774           // to the collection of PFElectrons in the python configuration
0775           // I don't know what to do with the efficiencyLoader, since I don't know
0776           // what this class is for.
0777           fillElectron2(
0778               anElectron, ptrToPFElectron, ptrToGsfElectron, ptrToGsfElectron, genMatches, deposits, isolationValues);
0779 
0780           //COLIN need to use fillElectron2 in the non-pflow case as well, and to test it.
0781 
0782           if (computeMiniIso_)
0783             setElectronMiniIso(anElectron, pc.product());
0784 
0785           patElectrons->push_back(anElectron);
0786         }
0787       }
0788       //if( !Matched && !MatchedToAmbiguousGsfTrack) std::cout << "!!!!A pf electron could not be matched to a gsf!!!!"  << std::endl;
0789     }
0790   }
0791 
0792   else {
0793     edm::Handle<reco::PFCandidateCollection> pfElectrons;
0794     edm::Handle<edm::ValueMap<reco::PFCandidatePtr>> ValMapH;
0795     edm::Handle<edm::ValueMap<std::vector<reco::PFCandidateRef>>> ValMultiMapH;
0796     bool pfCandsPresent = false, valMapPresent = false;
0797     if (usePfCandidateMultiMap_) {
0798       iEvent.getByToken(pfCandidateMultiMapToken_, ValMultiMapH);
0799     } else {
0800       pfCandsPresent = iEvent.getByToken(pfElecToken_, pfElectrons);
0801       valMapPresent = iEvent.getByToken(pfCandidateMapToken_, ValMapH);
0802     }
0803 
0804     for (edm::View<reco::GsfElectron>::const_iterator itElectron = electrons->begin(); itElectron != electrons->end();
0805          ++itElectron) {
0806       // construct the Electron from the ref -> save ref to original object
0807       //FIXME: looks like a lot of instances could be turned into const refs
0808       unsigned int idx = itElectron - electrons->begin();
0809       edm::RefToBase<reco::GsfElectron> elecsRef = electrons->refAt(idx);
0810       reco::CandidateBaseRef elecBaseRef(elecsRef);
0811       Electron anElectron(elecsRef);
0812       auto elePtr = electrons->ptrAt(idx);
0813 
0814       // Is this GsfElectron also identified as an e- in the particle flow?
0815       bool pfId = false;
0816 
0817       if (usePfCandidateMultiMap_) {
0818         for (const reco::PFCandidateRef& pf : (*ValMultiMapH)[elePtr]) {
0819           if (pf->particleId() == reco::PFCandidate::e) {
0820             pfId = true;
0821             anElectron.setPFCandidateRef(pf);
0822             break;
0823           }
0824         }
0825       } else if (pfCandsPresent) {
0826         // PF electron collection not available.
0827         const reco::GsfTrackRef& trkRef = itElectron->gsfTrack();
0828         int index = 0;
0829         for (reco::PFCandidateConstIterator ie = pfElectrons->begin(); ie != pfElectrons->end(); ++ie, ++index) {
0830           if (ie->particleId() != reco::PFCandidate::e)
0831             continue;
0832           const reco::GsfTrackRef& pfTrkRef = ie->gsfTrackRef();
0833           if (trkRef == pfTrkRef) {
0834             pfId = true;
0835             reco::PFCandidateRef pfRef(pfElectrons, index);
0836             anElectron.setPFCandidateRef(pfRef);
0837             break;
0838           }
0839         }
0840       } else if (valMapPresent) {
0841         // use value map if PF collection not available
0842         const edm::ValueMap<reco::PFCandidatePtr>& myValMap(*ValMapH);
0843         // Get the PFCandidate
0844         const reco::PFCandidatePtr& pfElePtr(myValMap[elecsRef]);
0845         pfId = pfElePtr.isNonnull();
0846       }
0847       // set PFId function
0848       anElectron.setIsPF(pfId);
0849 
0850       // add resolution info
0851 
0852       // Isolation
0853       if (isolator_.enabled()) {
0854         isolator_.fill(*electrons, idx, isolatorTmpStorage_);
0855         typedef pat::helper::MultiIsolator::IsolationValuePairs IsolationValuePairs;
0856         // better to loop backwards, so the vector is resized less times
0857         for (IsolationValuePairs::const_reverse_iterator it = isolatorTmpStorage_.rbegin(),
0858                                                          ed = isolatorTmpStorage_.rend();
0859              it != ed;
0860              ++it) {
0861           anElectron.setIsolation(it->first, it->second);
0862         }
0863       }
0864 
0865       for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
0866         anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[elecsRef]);
0867       }
0868 
0869       // add electron ID info
0870       if (addElecID_) {
0871         for (size_t i = 0; i < elecIDSrcs_.size(); ++i) {
0872           ids[i].second = (*idhandles[i])[elecsRef];
0873         }
0874         anElectron.setElectronIDs(ids);
0875       }
0876 
0877       if (useUserData_) {
0878         userDataHelper_.add(anElectron, iEvent, iSetup);
0879       }
0880 
0881       double ip3d = -999;  //for mva variable
0882 
0883       // embed high level selection
0884       if (embedHighLevelSelection_) {
0885         // get the global track
0886         reco::GsfTrackRef track = itElectron->gsfTrack();
0887 
0888         // Make sure the collection it points to is there
0889         if (track.isNonnull() && track.isAvailable()) {
0890           reco::TransientTrack tt = trackBuilder->build(track);
0891           embedHighLevel(anElectron, track, tt, primaryVertex, primaryVertexIsValid, beamSpot, beamSpotIsValid);
0892 
0893           std::pair<bool, Measurement1D> ip3dpv = IPTools::absoluteImpactParameter3D(tt, primaryVertex);
0894           ip3d = ip3dpv.second.value();  // for mva variable
0895         }
0896       }
0897 
0898       if (addMVAVariables_) {
0899         // add mva variables
0900         const auto& vCov = lazyTools.localCovariances(*(itElectron->superCluster()->seed()));
0901         anElectron.setMvaVariables(vCov[1], ip3d);
0902       }
0903 
0904       // PFCluster Isolation
0905       if (addPFClusterIso_) {
0906         // Get PFCluster Isolation
0907         edm::Handle<edm::ValueMap<float>> ecalPFClusterIsoMapH;
0908         iEvent.getByToken(ecalPFClusterIsoT_, ecalPFClusterIsoMapH);
0909         edm::Handle<edm::ValueMap<float>> hcalPFClusterIsoMapH;
0910         iEvent.getByToken(hcalPFClusterIsoT_, hcalPFClusterIsoMapH);
0911         reco::GsfElectron::PflowIsolationVariables newPFIsol = anElectron.pfIsolationVariables();
0912         newPFIsol.sumEcalClusterEt = (*ecalPFClusterIsoMapH)[elecsRef];
0913         newPFIsol.sumHcalClusterEt = (*hcalPFClusterIsoMapH)[elecsRef];
0914         anElectron.setPfIsolationVariables(newPFIsol);
0915       }
0916 
0917       if (addPuppiIsolation_) {
0918         anElectron.setIsolationPUPPI((*PUPPIIsolation_charged_hadrons)[elePtr],
0919                                      (*PUPPIIsolation_neutral_hadrons)[elePtr],
0920                                      (*PUPPIIsolation_photons)[elePtr]);
0921         anElectron.setIsolationPUPPINoLeptons((*PUPPINoLeptonsIsolation_charged_hadrons)[elePtr],
0922                                               (*PUPPINoLeptonsIsolation_neutral_hadrons)[elePtr],
0923                                               (*PUPPINoLeptonsIsolation_photons)[elePtr]);
0924       } else {
0925         anElectron.setIsolationPUPPI(-999., -999., -999.);
0926         anElectron.setIsolationPUPPINoLeptons(-999., -999., -999.);
0927       }
0928 
0929       std::vector<DetId> selectedCells;
0930       bool barrel = itElectron->isEB();
0931       //loop over sub clusters
0932       if (embedBasicClusters_) {
0933         for (reco::CaloCluster_iterator clusIt = itElectron->superCluster()->clustersBegin();
0934              clusIt != itElectron->superCluster()->clustersEnd();
0935              ++clusIt) {
0936           //get seed (max energy xtal)
0937           DetId seed = lazyTools.getMaximum(**clusIt).first;
0938           //get all xtals in 5x5 window around the seed
0939           std::vector<DetId> dets5x5 =
0940               (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0941                        : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0942           selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0943 
0944           //get all xtals belonging to cluster
0945           for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0946             selectedCells.push_back(hit.first);
0947           }
0948         }
0949       }
0950 
0951       if (embedPflowBasicClusters_ && itElectron->parentSuperCluster().isNonnull()) {
0952         for (reco::CaloCluster_iterator clusIt = itElectron->parentSuperCluster()->clustersBegin();
0953              clusIt != itElectron->parentSuperCluster()->clustersEnd();
0954              ++clusIt) {
0955           //get seed (max energy xtal)
0956           DetId seed = lazyTools.getMaximum(**clusIt).first;
0957           //get all xtals in 5x5 window around the seed
0958           std::vector<DetId> dets5x5 =
0959               (barrel) ? ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalBarrel)->getWindow(seed, 5, 5)
0960                        : ecalTopology_->getSubdetectorTopology(DetId::Ecal, EcalEndcap)->getWindow(seed, 5, 5);
0961           selectedCells.insert(selectedCells.end(), dets5x5.begin(), dets5x5.end());
0962 
0963           //get all xtals belonging to cluster
0964           for (const std::pair<DetId, float>& hit : (*clusIt)->hitsAndFractions()) {
0965             selectedCells.push_back(hit.first);
0966           }
0967         }
0968       }
0969 
0970       //remove duplicates
0971       std::sort(selectedCells.begin(), selectedCells.end());
0972       auto last = std::unique(selectedCells.begin(), selectedCells.end());
0973       selectedCells.erase(last, selectedCells.end());
0974 
0975       // Retrieve the corresponding RecHits
0976 
0977       edm::Handle<EcalRecHitCollection> rechitsH;
0978       if (barrel)
0979         iEvent.getByToken(reducedBarrelRecHitCollectionToken_, rechitsH);
0980       else
0981         iEvent.getByToken(reducedEndcapRecHitCollectionToken_, rechitsH);
0982 
0983       EcalRecHitCollection selectedRecHits;
0984       const EcalRecHitCollection* recHits = rechitsH.product();
0985 
0986       unsigned nSelectedCells = selectedCells.size();
0987       for (unsigned icell = 0; icell < nSelectedCells; ++icell) {
0988         EcalRecHitCollection::const_iterator it = recHits->find(selectedCells[icell]);
0989         if (it != recHits->end()) {
0990           selectedRecHits.push_back(*it);
0991         }
0992       }
0993       selectedRecHits.sort();
0994       if (embedRecHits_)
0995         anElectron.embedRecHits(&selectedRecHits);
0996 
0997       // set conversion veto selection
0998       bool passconversionveto = false;
0999       if (hConversions.isValid()) {
1000         // this is recommended method
1001         passconversionveto =
1002             !ConversionTools::hasMatchedConversion(*itElectron, *hConversions, beamSpotHandle->position());
1003       } else {
1004         // use missing hits without vertex fit method
1005         passconversionveto =
1006             itElectron->gsfTrack()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS) < 1;
1007       }
1008       anElectron.setPassConversionVeto(passconversionveto);
1009 
1010       // add sel to selected
1011       fillElectron(
1012           anElectron, elecsRef, elecBaseRef, genMatches, deposits, pfId, isolationValues, isolationValuesNoPFId);
1013 
1014       if (computeMiniIso_)
1015         setElectronMiniIso(anElectron, pc.product());
1016 
1017       patElectrons->push_back(anElectron);
1018     }
1019   }
1020 
1021   // sort electrons in pt
1022   std::sort(patElectrons->begin(), patElectrons->end(), pTComparator_);
1023 
1024   // add the electrons to the event output
1025   std::unique_ptr<std::vector<Electron>> ptr(patElectrons);
1026   iEvent.put(std::move(ptr));
1027 
1028   // clean up
1029   if (isolator_.enabled())
1030     isolator_.endEvent();
1031 }
1032 
1033 void PATElectronProducer::fillElectron(Electron& anElectron,
1034                                        const edm::RefToBase<reco::GsfElectron>& elecRef,
1035                                        const reco::CandidateBaseRef& baseRef,
1036                                        const GenAssociations& genMatches,
1037                                        const IsoDepositMaps& deposits,
1038                                        const bool pfId,
1039                                        const IsolationValueMaps& isolationValues,
1040                                        const IsolationValueMaps& isolationValuesNoPFId) const {
1041   //COLIN: might want to use the PFCandidate 4-mom. Which one is in use now?
1042   //   if (useParticleFlow_)
1043   //     aMuon.setP4( aMuon.pfCandidateRef()->p4() );
1044 
1045   //COLIN:
1046   //In the embedding case, the reference cannot be used to look into a value map.
1047   //therefore, one has to had the PFCandidateRef to this function, which becomes a bit
1048   //too much specific.
1049 
1050   // in fact, this function needs a baseref or ptr for genmatch
1051   // and a baseref or ptr for isodeposits and isolationvalues.
1052   // baseref is not needed
1053   // the ptrForIsolation and ptrForMatching should be defined upstream.
1054 
1055   // is the concrete elecRef needed for the efficiency loader? what is this loader?
1056   // how can we make it compatible with the particle flow electrons?
1057 
1058   if (embedGsfElectronCore_)
1059     anElectron.embedGsfElectronCore();
1060   if (embedGsfTrack_)
1061     anElectron.embedGsfTrack();
1062   if (embedSuperCluster_)
1063     anElectron.embedSuperCluster();
1064   if (embedPflowSuperCluster_)
1065     anElectron.embedPflowSuperCluster();
1066   if (embedSeedCluster_)
1067     anElectron.embedSeedCluster();
1068   if (embedBasicClusters_)
1069     anElectron.embedBasicClusters();
1070   if (embedPreshowerClusters_)
1071     anElectron.embedPreshowerClusters();
1072   if (embedPflowBasicClusters_)
1073     anElectron.embedPflowBasicClusters();
1074   if (embedPflowPreshowerClusters_)
1075     anElectron.embedPflowPreshowerClusters();
1076   if (embedTrack_)
1077     anElectron.embedTrack();
1078 
1079   // store the match to the generated final state muons
1080   if (addGenMatch_) {
1081     for (size_t i = 0, n = genMatches.size(); i < n; ++i) {
1082       if (useParticleFlow_) {
1083         reco::GenParticleRef genElectron = (*genMatches[i])[anElectron.pfCandidateRef()];
1084         anElectron.addGenParticleRef(genElectron);
1085       } else {
1086         reco::GenParticleRef genElectron = (*genMatches[i])[elecRef];
1087         anElectron.addGenParticleRef(genElectron);
1088       }
1089     }
1090     if (embedGenMatch_)
1091       anElectron.embedGenParticle();
1092   }
1093 
1094   if (efficiencyLoader_.enabled()) {
1095     efficiencyLoader_.setEfficiencies(anElectron, elecRef);
1096   }
1097 
1098   if (resolutionLoader_.enabled()) {
1099     resolutionLoader_.setResolutions(anElectron);
1100   }
1101 
1102   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
1103     if (useParticleFlow_) {
1104       reco::PFCandidateRef pfcandref = anElectron.pfCandidateRef();
1105       assert(!pfcandref.isNull());
1106       reco::CandidatePtr source = pfcandref->sourceCandidatePtr(0);
1107       anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[source]);
1108     } else
1109       anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[elecRef]);
1110   }
1111 
1112   for (size_t j = 0; j < isolationValues.size(); ++j) {
1113     if (useParticleFlow_) {
1114       reco::CandidatePtr source = anElectron.pfCandidateRef()->sourceCandidatePtr(0);
1115       anElectron.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[source]);
1116     } else if (pfId) {
1117       anElectron.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[elecRef]);
1118     }
1119   }
1120 
1121   //for electrons not identified as PF electrons
1122   for (size_t j = 0; j < isolationValuesNoPFId.size(); ++j) {
1123     if (!pfId) {
1124       anElectron.setIsolation(isolationValueLabelsNoPFId_[j].first, (*isolationValuesNoPFId[j])[elecRef]);
1125     }
1126   }
1127 }
1128 
1129 void PATElectronProducer::fillElectron2(Electron& anElectron,
1130                                         const reco::CandidatePtr& candPtrForIsolation,
1131                                         const reco::CandidatePtr& candPtrForGenMatch,
1132                                         const reco::CandidatePtr& candPtrForLoader,
1133                                         const GenAssociations& genMatches,
1134                                         const IsoDepositMaps& deposits,
1135                                         const IsolationValueMaps& isolationValues) const {
1136   //COLIN/Florian: use the PFCandidate 4-mom.
1137   anElectron.setEcalDrivenMomentum(anElectron.p4());
1138   anElectron.setP4(anElectron.pfCandidateRef()->p4());
1139 
1140   // is the concrete elecRef needed for the efficiency loader? what is this loader?
1141   // how can we make it compatible with the particle flow electrons?
1142 
1143   if (embedGsfElectronCore_)
1144     anElectron.embedGsfElectronCore();
1145   if (embedGsfTrack_)
1146     anElectron.embedGsfTrack();
1147   if (embedSuperCluster_)
1148     anElectron.embedSuperCluster();
1149   if (embedPflowSuperCluster_)
1150     anElectron.embedPflowSuperCluster();
1151   if (embedSeedCluster_)
1152     anElectron.embedSeedCluster();
1153   if (embedBasicClusters_)
1154     anElectron.embedBasicClusters();
1155   if (embedPreshowerClusters_)
1156     anElectron.embedPreshowerClusters();
1157   if (embedPflowBasicClusters_)
1158     anElectron.embedPflowBasicClusters();
1159   if (embedPflowPreshowerClusters_)
1160     anElectron.embedPflowPreshowerClusters();
1161   if (embedTrack_)
1162     anElectron.embedTrack();
1163 
1164   // store the match to the generated final state muons
1165 
1166   if (addGenMatch_) {
1167     for (size_t i = 0, n = genMatches.size(); i < n; ++i) {
1168       reco::GenParticleRef genElectron = (*genMatches[i])[candPtrForGenMatch];
1169       anElectron.addGenParticleRef(genElectron);
1170     }
1171     if (embedGenMatch_)
1172       anElectron.embedGenParticle();
1173   }
1174 
1175   //COLIN what's this? does it have to be GsfElectron specific?
1176   if (efficiencyLoader_.enabled()) {
1177     efficiencyLoader_.setEfficiencies(anElectron, candPtrForLoader);
1178   }
1179 
1180   if (resolutionLoader_.enabled()) {
1181     resolutionLoader_.setResolutions(anElectron);
1182   }
1183 
1184   for (size_t j = 0, nd = deposits.size(); j < nd; ++j) {
1185     if (isoDepositLabels_[j].first == pat::TrackIso || isoDepositLabels_[j].first == pat::EcalIso ||
1186         isoDepositLabels_[j].first == pat::HcalIso || deposits[j]->contains(candPtrForGenMatch.id())) {
1187       anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[candPtrForGenMatch]);
1188     } else if (deposits[j]->contains(candPtrForIsolation.id())) {
1189       anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[candPtrForIsolation]);
1190     } else {
1191       anElectron.setIsoDeposit(isoDepositLabels_[j].first, (*deposits[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
1192     }
1193   }
1194 
1195   for (size_t j = 0; j < isolationValues.size(); ++j) {
1196     if (isolationValueLabels_[j].first == pat::TrackIso || isolationValueLabels_[j].first == pat::EcalIso ||
1197         isolationValueLabels_[j].first == pat::HcalIso || isolationValues[j]->contains(candPtrForGenMatch.id())) {
1198       anElectron.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[candPtrForGenMatch]);
1199     } else if (isolationValues[j]->contains(candPtrForIsolation.id())) {
1200       anElectron.setIsolation(isolationValueLabels_[j].first, (*isolationValues[j])[candPtrForIsolation]);
1201     } else {
1202       anElectron.setIsolation(isolationValueLabels_[j].first,
1203                               (*isolationValues[j])[candPtrForIsolation->sourceCandidatePtr(0)]);
1204     }
1205   }
1206 }
1207 
1208 void PATElectronProducer::setElectronMiniIso(Electron& anElectron, const PackedCandidateCollection* pc) {
1209   pat::PFIsolation miniiso;
1210   if (anElectron.isEE())
1211     miniiso = pat::getMiniPFIsolation(pc,
1212                                       anElectron.polarP4(),
1213                                       miniIsoParamsE_[0],
1214                                       miniIsoParamsE_[1],
1215                                       miniIsoParamsE_[2],
1216                                       miniIsoParamsE_[3],
1217                                       miniIsoParamsE_[4],
1218                                       miniIsoParamsE_[5],
1219                                       miniIsoParamsE_[6],
1220                                       miniIsoParamsE_[7],
1221                                       miniIsoParamsE_[8]);
1222   else
1223     miniiso = pat::getMiniPFIsolation(pc,
1224                                       anElectron.polarP4(),
1225                                       miniIsoParamsB_[0],
1226                                       miniIsoParamsB_[1],
1227                                       miniIsoParamsB_[2],
1228                                       miniIsoParamsB_[3],
1229                                       miniIsoParamsB_[4],
1230                                       miniIsoParamsB_[5],
1231                                       miniIsoParamsB_[6],
1232                                       miniIsoParamsB_[7],
1233                                       miniIsoParamsB_[8]);
1234   anElectron.setMiniPFIsolation(miniiso);
1235 }
1236 
1237 // ParameterSet description for module
1238 void PATElectronProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
1239   edm::ParameterSetDescription iDesc;
1240   iDesc.setComment("PAT electron producer module");
1241 
1242   // input source
1243   iDesc.add<edm::InputTag>("pfCandidateMap", edm::InputTag("no default"))->setComment("input collection");
1244   iDesc.add<edm::InputTag>("electronSource", edm::InputTag("no default"))->setComment("input collection");
1245 
1246   iDesc.ifValue(
1247       edm::ParameterDescription<bool>("addPFClusterIso", false, true),
1248       true >> (edm::ParameterDescription<edm::InputTag>(
1249                    "ecalPFClusterIsoMap", edm::InputTag("electronEcalPFClusterIsolationProducer"), true) and
1250                edm::ParameterDescription<edm::InputTag>(
1251                    "hcalPFClusterIsoMap", edm::InputTag("electronHcalPFClusterIsolationProducer"), true)) or
1252           false >> (edm::ParameterDescription<edm::InputTag>("ecalPFClusterIsoMap", edm::InputTag(""), true) and
1253                     edm::ParameterDescription<edm::InputTag>("hcalPFClusterIsoMap", edm::InputTag(""), true)));
1254 
1255   iDesc.ifValue(edm::ParameterDescription<bool>("addPuppiIsolation", false, true),
1256                 true >> (edm::ParameterDescription<edm::InputTag>(
1257                              "puppiIsolationChargedHadrons",
1258                              edm::InputTag("egmElectronPUPPIIsolation", "h+-DR030-BarVeto000-EndVeto001"),
1259                              true) and
1260                          edm::ParameterDescription<edm::InputTag>(
1261                              "puppiIsolationNeutralHadrons",
1262                              edm::InputTag("egmElectronPUPPIIsolation", "h0-DR030-BarVeto000-EndVeto000"),
1263                              true) and
1264                          edm::ParameterDescription<edm::InputTag>(
1265                              "puppiIsolationPhotons",
1266                              edm::InputTag("egmElectronPUPPIIsolation", "gamma-DR030-BarVeto000-EndVeto008"),
1267                              true) and
1268                          edm::ParameterDescription<edm::InputTag>(
1269                              "puppiNoLeptonsIsolationChargedHadrons",
1270                              edm::InputTag("egmElectronPUPPINoLeptonsIsolation", "gamma-DR030-BarVeto000-EndVeto008"),
1271                              true) and
1272                          edm::ParameterDescription<edm::InputTag>(
1273                              "puppiNoLeptonsIsolationNeutralHadrons",
1274                              edm::InputTag("egmElectronPUPPINoLeptonsIsolation", "gamma-DR030-BarVeto000-EndVeto008"),
1275                              true) and
1276                          edm::ParameterDescription<edm::InputTag>(
1277                              "puppiNoLeptonsIsolationPhotons",
1278                              edm::InputTag("egmElectronPUPPINoLeptonsIsolation", "gamma-DR030-BarVeto000-EndVeto008"),
1279                              true)) or
1280                     false >> edm::EmptyGroupDescription());
1281 
1282   // embedding
1283   iDesc.add<bool>("embedGsfElectronCore", true)->setComment("embed external gsf electron core");
1284   iDesc.add<bool>("embedGsfTrack", true)->setComment("embed external gsf track");
1285   iDesc.add<bool>("embedSuperCluster", true)->setComment("embed external super cluster");
1286   iDesc.add<bool>("embedPflowSuperCluster", true)->setComment("embed external super cluster");
1287   iDesc.add<bool>("embedSeedCluster", true)->setComment("embed external seed cluster");
1288   iDesc.add<bool>("embedBasicClusters", true)->setComment("embed external basic clusters");
1289   iDesc.add<bool>("embedPreshowerClusters", true)->setComment("embed external preshower clusters");
1290   iDesc.add<bool>("embedPflowBasicClusters", true)->setComment("embed external pflow basic clusters");
1291   iDesc.add<bool>("embedPflowPreshowerClusters", true)->setComment("embed external pflow preshower clusters");
1292   iDesc.add<bool>("embedTrack", false)->setComment("embed external track");
1293   iDesc.add<bool>("embedRecHits", true)->setComment("embed external RecHits");
1294 
1295   // pf specific parameters
1296   iDesc.add<edm::InputTag>("pfElectronSource", edm::InputTag("pfElectrons"))
1297       ->setComment("particle flow input collection");
1298   auto&& usePfCandidateMultiMap = edm::ParameterDescription<bool>("usePfCandidateMultiMap", false, true);
1299   usePfCandidateMultiMap.setComment(
1300       "take ParticleFlow candidates from pfCandidateMultiMap instead of matching to pfElectrons by Gsf track "
1301       "reference");
1302   iDesc.ifValue(usePfCandidateMultiMap,
1303                 true >> edm::ParameterDescription<edm::InputTag>("pfCandidateMultiMap", true) or
1304                     false >> edm::EmptyGroupDescription());
1305   iDesc.add<bool>("useParticleFlow", false)->setComment("whether to use particle flow or not");
1306   iDesc.add<bool>("embedPFCandidate", false)->setComment("embed external particle flow object");
1307 
1308   // MC matching configurables
1309   iDesc.add<bool>("addGenMatch", true)->setComment("add MC matching");
1310   iDesc.add<bool>("embedGenMatch", false)->setComment("embed MC matched MC information");
1311   std::vector<edm::InputTag> emptySourceVector;
1312   iDesc
1313       .addNode(edm::ParameterDescription<edm::InputTag>("genParticleMatch", edm::InputTag(), true) xor
1314                edm::ParameterDescription<std::vector<edm::InputTag>>("genParticleMatch", emptySourceVector, true))
1315       ->setComment("input with MC match information");
1316 
1317   // electron ID configurables
1318   iDesc.add<bool>("addElectronID", true)->setComment("add electron ID variables");
1319   edm::ParameterSetDescription electronIDSourcesPSet;
1320   electronIDSourcesPSet.setAllowAnything();
1321   iDesc
1322       .addNode(
1323           edm::ParameterDescription<edm::InputTag>("electronIDSource", edm::InputTag(), true) xor
1324           edm::ParameterDescription<edm::ParameterSetDescription>("electronIDSources", electronIDSourcesPSet, true))
1325       ->setComment("input with electron ID variables");
1326 
1327   // mini-iso
1328   iDesc.add<bool>("computeMiniIso", false)->setComment("whether or not to compute and store electron mini-isolation");
1329   iDesc.add<edm::InputTag>("pfCandsForMiniIso", edm::InputTag("packedPFCandidates"))
1330       ->setComment("collection to use to compute mini-iso");
1331   iDesc.add<std::vector<double>>("miniIsoParamsE", std::vector<double>())
1332       ->setComment("mini-iso parameters to use for endcap electrons");
1333   iDesc.add<std::vector<double>>("miniIsoParamsB", std::vector<double>())
1334       ->setComment("mini-iso parameters to use for barrel electrons");
1335 
1336   // IsoDeposit configurables
1337   edm::ParameterSetDescription isoDepositsPSet;
1338   isoDepositsPSet.addOptional<edm::InputTag>("tracker");
1339   isoDepositsPSet.addOptional<edm::InputTag>("ecal");
1340   isoDepositsPSet.addOptional<edm::InputTag>("hcal");
1341   isoDepositsPSet.addOptional<edm::InputTag>("pfAllParticles");
1342   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedHadrons");
1343   isoDepositsPSet.addOptional<edm::InputTag>("pfChargedAll");
1344   isoDepositsPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
1345   isoDepositsPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
1346   isoDepositsPSet.addOptional<edm::InputTag>("pfPhotons");
1347   isoDepositsPSet.addOptional<std::vector<edm::InputTag>>("user");
1348   iDesc.addOptional("isoDeposits", isoDepositsPSet);
1349 
1350   // isolation values configurables
1351   edm::ParameterSetDescription isolationValuesPSet;
1352   isolationValuesPSet.addOptional<edm::InputTag>("tracker");
1353   isolationValuesPSet.addOptional<edm::InputTag>("ecal");
1354   isolationValuesPSet.addOptional<edm::InputTag>("hcal");
1355   isolationValuesPSet.addOptional<edm::InputTag>("pfAllParticles");
1356   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedHadrons");
1357   isolationValuesPSet.addOptional<edm::InputTag>("pfChargedAll");
1358   isolationValuesPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
1359   isolationValuesPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
1360   isolationValuesPSet.addOptional<edm::InputTag>("pfPhotons");
1361   isolationValuesPSet.addOptional<std::vector<edm::InputTag>>("user");
1362   iDesc.addOptional("isolationValues", isolationValuesPSet);
1363 
1364   // isolation values configurables
1365   edm::ParameterSetDescription isolationValuesNoPFIdPSet;
1366   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("tracker");
1367   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("ecal");
1368   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("hcal");
1369   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfAllParticles");
1370   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfChargedHadrons");
1371   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfChargedAll");
1372   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfPUChargedHadrons");
1373   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfNeutralHadrons");
1374   isolationValuesNoPFIdPSet.addOptional<edm::InputTag>("pfPhotons");
1375   isolationValuesNoPFIdPSet.addOptional<std::vector<edm::InputTag>>("user");
1376   iDesc.addOptional("isolationValuesNoPFId", isolationValuesNoPFIdPSet);
1377 
1378   // Efficiency configurables
1379   edm::ParameterSetDescription efficienciesPSet;
1380   efficienciesPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
1381   iDesc.add("efficiencies", efficienciesPSet);
1382   iDesc.add<bool>("addEfficiencies", false);
1383 
1384   // Check to see if the user wants to add user data
1385   edm::ParameterSetDescription userDataPSet;
1386   PATUserDataHelper<Electron>::fillDescription(userDataPSet);
1387   iDesc.addOptional("userData", userDataPSet);
1388 
1389   // electron shapes
1390   iDesc.add<bool>("addMVAVariables", true)->setComment("embed extra variables in pat::Electron : sip3d, sigmaIEtaIPhi");
1391   iDesc.add<edm::InputTag>("reducedBarrelRecHitCollection", edm::InputTag("reducedEcalRecHitsEB"));
1392   iDesc.add<edm::InputTag>("reducedEndcapRecHitCollection", edm::InputTag("reducedEcalRecHitsEE"));
1393 
1394   edm::ParameterSetDescription isolationPSet;
1395   isolationPSet.setAllowAnything();  // TODO: the pat helper needs to implement a description.
1396   iDesc.add("userIsolation", isolationPSet);
1397 
1398   // Resolution configurables
1399   pat::helper::KinResolutionsLoader::fillDescription(iDesc);
1400 
1401   iDesc.add<bool>("embedHighLevelSelection", true)->setComment("embed high level selection");
1402   edm::ParameterSetDescription highLevelPSet;
1403   highLevelPSet.setAllowAnything();
1404   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("beamLineSrc", edm::InputTag(), true))
1405       ->setComment("input with high level selection");
1406   iDesc.addNode(edm::ParameterDescription<edm::InputTag>("pvSrc", edm::InputTag(), true))
1407       ->setComment("input with high level selection");
1408 
1409   descriptions.add("PATElectronProducer", iDesc);
1410 }
1411 
1412 // embed various impact parameters with errors
1413 // embed high level selection
1414 void PATElectronProducer::embedHighLevel(pat::Electron& anElectron,
1415                                          reco::GsfTrackRef track,
1416                                          reco::TransientTrack& tt,
1417                                          reco::Vertex& primaryVertex,
1418                                          bool primaryVertexIsValid,
1419                                          reco::BeamSpot& beamspot,
1420                                          bool beamspotIsValid) {
1421   // Correct to PV
1422   // PV2D
1423   anElectron.setDB(track->dxy(primaryVertex.position()),
1424                    track->dxyError(primaryVertex.position(), primaryVertex.covariance()),
1425                    pat::Electron::PV2D);
1426 
1427   // PV3D
1428   std::pair<bool, Measurement1D> result =
1429       IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), primaryVertex);
1430   double d0_corr = result.second.value();
1431   double d0_err = primaryVertexIsValid ? result.second.error() : -1.0;
1432   anElectron.setDB(d0_corr, d0_err, pat::Electron::PV3D);
1433 
1434   // Correct to beam spot
1435   // BS2D
1436   anElectron.setDB(track->dxy(beamspot), track->dxyError(beamspot), pat::Electron::BS2D);
1437 
1438   // make a fake vertex out of beam spot
1439   reco::Vertex vBeamspot(beamspot.position(), beamspot.covariance3D());
1440 
1441   // BS3D
1442   result = IPTools::signedImpactParameter3D(tt, GlobalVector(track->px(), track->py(), track->pz()), vBeamspot);
1443   d0_corr = result.second.value();
1444   d0_err = beamspotIsValid ? result.second.error() : -1.0;
1445   anElectron.setDB(d0_corr, d0_err, pat::Electron::BS3D);
1446 
1447   // PVDZ
1448   anElectron.setDB(
1449       track->dz(primaryVertex.position()), std::hypot(track->dzError(), primaryVertex.zError()), pat::Electron::PVDZ);
1450 }
1451 
1452 #include "FWCore/Framework/interface/MakerMacros.h"
1453 DEFINE_FWK_MODULE(PATElectronProducer);