Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-11-29 01:33:05

0001 #include "CommonTools/Utils/interface/StringToEnumValue.h"
0002 #include "DataFormats/Common/interface/Handle.h"
0003 #include "DataFormats/EcalRecHit/interface/EcalSeverityLevel.h"
0004 #include "DataFormats/EgammaCandidates/interface/GsfElectron.h"
0005 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
0006 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
0007 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidate.h"
0008 #include "DataFormats/ParticleFlowCandidate/interface/PFCandidateEGammaExtra.h"
0009 #include "DataFormats/ParticleFlowReco/interface/GsfPFRecTrack.h"
0010 #include "DataFormats/TrackCandidate/interface/TrackCandidateCollection.h"
0011 #include "FWCore/Common/interface/Provenance.h"
0012 #include "FWCore/Framework/interface/Event.h"
0013 #include "FWCore/Framework/interface/EventSetup.h"
0014 #include "FWCore/Framework/interface/stream/EDProducer.h"
0015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0016 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0019 #include "RecoEcal/EgammaCoreTools/interface/EcalClusterFunctionFactory.h"
0020 #include "RecoEgamma/EgammaIsolationAlgos/interface/EleTkIsolFromCands.h"
0021 #include "RecoEgamma/EgammaElectronAlgos/interface/EgAmbiguityTools.h"
0022 #include "RecoEgamma/EgammaElectronAlgos/interface/ElectronUtilities.h"
0023 #include "RecoEgamma/EgammaElectronAlgos/interface/GsfElectronAlgo.h"
0024 #include "RecoEcal/EgammaCoreTools/interface/EgammaLocalCovParamDefaults.h"
0025 #include "RecoEgamma/EgammaIsolationAlgos/interface/EcalPFClusterIsolation.h"
0026 #include "RecoEgamma/EgammaIsolationAlgos/interface/HcalPFClusterIsolation.h"
0027 
0028 #include <array>
0029 
0030 using namespace reco;
0031 
0032 namespace {
0033 
0034   void setMVAOutputs(reco::GsfElectronCollection& electrons,
0035                      const GsfElectronAlgo::HeavyObjectCache* hoc,
0036                      reco::VertexCollection const& vertices,
0037                      bool dnnPFidEnabled,
0038                      float extetaboundary,
0039                      const std::vector<tensorflow::Session*>& tfSessions) {
0040     std::vector<GsfElectron::MvaOutput> mva_outputs(electrons.size());
0041     size_t iele = 0;
0042     for (auto& el : electrons) {
0043       GsfElectron::MvaOutput mvaOutput;
0044       mvaOutput.mva_e_pi = hoc->sElectronMVAEstimator->mva(el, vertices);
0045       mvaOutput.mva_Isolated = hoc->iElectronMVAEstimator->mva(el, vertices.size());
0046       if (dnnPFidEnabled) {
0047         mva_outputs[iele] = mvaOutput;
0048       } else {
0049         el.setMvaOutput(mvaOutput);
0050       }
0051       iele++;
0052     }
0053     if (dnnPFidEnabled) {
0054       // Here send the list of electrons to the ElectronDNNEstimator and get back the values for all the electrons in one go
0055       LogDebug("GsfElectronProducer") << "Getting DNN PFId for ele";
0056       const auto& dnn_ele_pfid = hoc->iElectronDNNEstimator->evaluate(electrons, tfSessions);
0057       int jele = 0;
0058       for (auto& el : electrons) {
0059         const auto& [iModel, values] = dnn_ele_pfid[jele];
0060         // get the previous values
0061         auto& mvaOutput = mva_outputs[jele];
0062 
0063         if (iModel <= 3) {  // models 0,1,2,3 have 5 outputs in this version
0064           assert(values.size() == 5);
0065           mvaOutput.dnn_e_sigIsolated = values[0];
0066           mvaOutput.dnn_e_sigNonIsolated = values[1];
0067           mvaOutput.dnn_e_bkgNonIsolated = values[2];
0068           mvaOutput.dnn_e_bkgTau = values[3];
0069           mvaOutput.dnn_e_bkgPhoton = values[4];
0070         } else if (iModel == 4) {  //etaExtended model has 3 outputs
0071           assert(values.size() == 3);
0072           mvaOutput.dnn_e_sigIsolated = values[0];
0073           mvaOutput.dnn_e_sigNonIsolated = 0.0;
0074           mvaOutput.dnn_e_bkgNonIsolated = values[1];
0075           mvaOutput.dnn_e_bkgTau = 0.0;
0076           mvaOutput.dnn_e_bkgPhoton = values[2];
0077         }
0078         el.setMvaOutput(mvaOutput);
0079         jele++;
0080       }
0081     }
0082   }
0083 
0084   // Something more clever has to be found. The collections are small, so the timing is not
0085   // an issue here; but it is clearly suboptimal
0086 
0087   auto matchWithPFCandidates(std::vector<reco::PFCandidate> const& pfCandidates) {
0088     std::map<reco::GsfTrackRef, reco::GsfElectron::MvaInput> gsfMVAInputs{};
0089 
0090     //Loop over the collection of PFFCandidates
0091     for (auto const& pfCand : pfCandidates) {
0092       reco::GsfElectronRef myRef;
0093       // First check that the GsfTrack is non null
0094       if (pfCand.gsfTrackRef().isNonnull()) {
0095         reco::GsfElectron::MvaInput input;
0096         input.earlyBrem = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_FirstBrem);
0097         input.lateBrem = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_LateBrem);
0098         input.deltaEta = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_DeltaEtaTrackCluster);
0099         input.sigmaEtaEta = pfCand.egammaExtraRef()->sigmaEtaEta();
0100         input.hadEnergy = pfCand.egammaExtraRef()->hadEnergy();
0101         gsfMVAInputs[pfCand.gsfTrackRef()] = input;
0102       }
0103     }
0104     return gsfMVAInputs;
0105   }
0106 
0107   void logElectrons(reco::GsfElectronCollection const& electrons, edm::Event const& event, const std::string& title) {
0108     LogTrace("GsfElectronAlgo") << "========== " << title << " ==========";
0109     LogTrace("GsfElectronAlgo") << "Event: " << event.id();
0110     LogTrace("GsfElectronAlgo") << "Number of electrons: " << electrons.size();
0111     for (auto const& ele : electrons) {
0112       LogTrace("GsfElectronAlgo") << "Electron with charge, pt, eta, phi: " << ele.charge() << " , " << ele.pt()
0113                                   << " , " << ele.eta() << " , " << ele.phi();
0114     }
0115     LogTrace("GsfElectronAlgo") << "=================================================";
0116   }
0117 
0118 }  // namespace
0119 
0120 class GsfElectronProducer : public edm::stream::EDProducer<edm::GlobalCache<GsfElectronAlgo::HeavyObjectCache>> {
0121 public:
0122   static void fillDescriptions(edm::ConfigurationDescriptions&);
0123 
0124   explicit GsfElectronProducer(const edm::ParameterSet&, const GsfElectronAlgo::HeavyObjectCache*);
0125 
0126   static std::unique_ptr<GsfElectronAlgo::HeavyObjectCache> initializeGlobalCache(const edm::ParameterSet& conf) {
0127     return std::make_unique<GsfElectronAlgo::HeavyObjectCache>(conf);
0128   }
0129 
0130   void endStream() override;
0131 
0132   static void globalEndJob(GsfElectronAlgo::HeavyObjectCache const*){};
0133 
0134   // ------------ method called to produce the data  ------------
0135   void beginRun(const edm::Run&, const edm::EventSetup&) override;
0136   void produce(edm::Event& event, const edm::EventSetup& setup) override;
0137 
0138 private:
0139   std::unique_ptr<GsfElectronAlgo> algo_;
0140 
0141   // configurables
0142   GsfElectronAlgo::Tokens inputCfg_;
0143   GsfElectronAlgo::StrategyConfiguration strategyCfg_;
0144   const GsfElectronAlgo::CutsConfiguration cutsCfg_;
0145   ElectronHcalHelper::Configuration hcalCfg_, hcalCfgBc_;
0146 
0147   bool hcalRun2EffDepth_;
0148 
0149   bool isPreselected(reco::GsfElectron const& ele) const;
0150   void setAmbiguityData(reco::GsfElectronCollection& electrons,
0151                         edm::Event const& event,
0152                         bool ignoreNotPreselected = true) const;
0153 
0154   // check expected configuration of previous modules
0155   bool ecalSeedingParametersChecked_;
0156   void checkEcalSeedingParameters(edm::ParameterSet const&);
0157 
0158   const edm::EDPutTokenT<reco::GsfElectronCollection> electronPutToken_;
0159   const edm::EDGetTokenT<reco::GsfPFRecTrackCollection> gsfPfRecTracksTag_;
0160   edm::EDGetTokenT<reco::PFCandidateCollection> egmPFCandidateCollection_;
0161 
0162   const bool useGsfPfRecTracks_;
0163 
0164   const bool resetMvaValuesUsingPFCandidates_;
0165 
0166   bool dnnPFidEnabled_;
0167   float extetaboundary_;
0168 
0169   std::vector<tensorflow::Session*> tfSessions_;
0170 
0171   edm::ESGetToken<HcalPFCuts, HcalPFCutsRcd> hcalCutsToken_;
0172   bool cutsFromDB;
0173   HcalPFCuts const* hcalCuts = nullptr;
0174 };
0175 
0176 void GsfElectronProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0177   edm::ParameterSetDescription desc;
0178   // input collections
0179   desc.add<edm::InputTag>("gsfElectronCoresTag", {"ecalDrivenGsfElectronCores"});
0180   desc.add<edm::InputTag>("vtxTag", {"offlinePrimaryVertices"});
0181   desc.add<edm::InputTag>("conversionsTag", {"allConversions"});
0182   desc.add<edm::InputTag>("gsfPfRecTracksTag", {"pfTrackElec"});
0183   desc.add<edm::InputTag>("barrelRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEB"});
0184   desc.add<edm::InputTag>("endcapRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEE"});
0185   desc.add<edm::InputTag>("seedsTag", {"ecalDrivenElectronSeeds"});
0186   desc.add<edm::InputTag>("beamSpotTag", {"offlineBeamSpot"});
0187   desc.add<edm::InputTag>("egmPFCandidatesTag", {"particleFlowEGamma"});
0188 
0189   // steering
0190   desc.add<bool>("useDefaultEnergyCorrection", true);
0191   desc.add<bool>("useCombinationRegression", false);
0192   desc.add<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization", true);
0193   desc.add<bool>("ecalDrivenEcalErrorFromClassBasedParameterization", true);
0194   desc.add<bool>("applyPreselection", false);
0195   desc.add<bool>("useEcalRegression", false);
0196   desc.add<bool>("applyAmbResolution", false);
0197   desc.add<bool>("ignoreNotPreselected", true);
0198   desc.add<bool>("useGsfPfRecTracks", true);
0199   desc.add<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization", true);
0200   desc.add<unsigned int>("ambSortingStrategy", 1);
0201   desc.add<unsigned int>("ambClustersOverlapStrategy", 1);
0202   desc.add<bool>("fillConvVtxFitProb", true);
0203   desc.add<bool>("resetMvaValuesUsingPFCandidates", false);
0204 
0205   // Ecal rec hits configuration
0206   desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
0207   desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
0208   desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
0209   desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
0210 
0211   // Hcal rec hits configuration
0212   desc.add<bool>("checkHcalStatus", true);
0213   desc.add<edm::InputTag>("hbheRecHits", edm::InputTag("hbhereco"));
0214   desc.add<std::vector<double>>("recHitEThresholdHB", {0., 0., 0., 0.});
0215   desc.add<std::vector<double>>("recHitEThresholdHE", {0., 0., 0., 0., 0., 0., 0.});
0216   desc.add<int>("maxHcalRecHitSeverity", 999999);
0217   desc.add<bool>("hcalRun2EffDepth", false);
0218   desc.add<bool>("usePFThresholdsFromDB", false);
0219 
0220   // Isolation algos configuration
0221   desc.add("trkIsol03Cfg", EleTkIsolFromCands::pSetDescript());
0222   desc.add("trkIsol04Cfg", EleTkIsolFromCands::pSetDescript());
0223   desc.add("trkIsolHEEP03Cfg", EleTkIsolFromCands::pSetDescript());
0224   desc.add("trkIsolHEEP04Cfg", EleTkIsolFromCands::pSetDescript());
0225   desc.add<bool>("useNumCrystals", true);
0226   desc.add<double>("etMinBarrel", 0.0);
0227   desc.add<double>("etMinEndcaps", 0.11);
0228   desc.add<double>("etMinHcal", 0.0);
0229   desc.add<double>("eMinBarrel", 0.095);
0230   desc.add<double>("eMinEndcaps", 0.0);
0231   desc.add<double>("intRadiusEcalBarrel", 3.0);
0232   desc.add<double>("intRadiusEcalEndcaps", 3.0);
0233   desc.add<double>("intRadiusHcal", 0.15);
0234   desc.add<double>("jurassicWidth", 1.5);
0235   desc.add<bool>("vetoClustered", false);
0236 
0237   // backward compatibility mechanism for ctf tracks
0238   desc.add<bool>("ctfTracksCheck", true);
0239   desc.add<edm::InputTag>("ctfTracksTag", {"generalTracks"});
0240 
0241   desc.add<double>("MaxElePtForOnlyMVA", 50.0);
0242   desc.add<double>("PreSelectMVA", -0.1);
0243 
0244   {
0245     edm::ParameterSetDescription psd0;
0246     psd0.add<double>("minSCEtBarrel", 4.0);
0247     psd0.add<double>("minSCEtEndcaps", 4.0);
0248     psd0.add<double>("minEOverPBarrel", 0.0);
0249     psd0.add<double>("minEOverPEndcaps", 0.0);
0250     psd0.add<double>("maxEOverPBarrel", 999999999.0);
0251     psd0.add<double>("maxEOverPEndcaps", 999999999.0);
0252     psd0.add<double>("maxDeltaEtaBarrel", 0.02);
0253     psd0.add<double>("maxDeltaEtaEndcaps", 0.02);
0254     psd0.add<double>("maxDeltaPhiBarrel", 0.15);
0255     psd0.add<double>("maxDeltaPhiEndcaps", 0.15);
0256     psd0.add<double>("hOverEConeSize", 0.15);
0257     psd0.add<double>("maxHOverEBarrelCone", 0.15);
0258     psd0.add<double>("maxHOverEEndcapsCone", 0.15);
0259     psd0.add<double>("maxHBarrelCone", 0.0);
0260     psd0.add<double>("maxHEndcapsCone", 0.0);
0261     psd0.add<double>("maxHOverEBarrelBc", 0.15);
0262     psd0.add<double>("maxHOverEEndcapsBc", 0.15);
0263     psd0.add<double>("maxHBarrelBc", 0.0);
0264     psd0.add<double>("maxHEndcapsBc", 0.0);
0265     psd0.add<double>("maxSigmaIetaIetaBarrel", 999999999.0);
0266     psd0.add<double>("maxSigmaIetaIetaEndcaps", 999999999.0);
0267     psd0.add<double>("maxFbremBarrel", 999999999.0);
0268     psd0.add<double>("maxFbremEndcaps", 999999999.0);
0269     psd0.add<bool>("isBarrel", false);
0270     psd0.add<bool>("isEndcaps", false);
0271     psd0.add<bool>("isFiducial", false);
0272     psd0.add<bool>("seedFromTEC", true);
0273     psd0.add<double>("maxTIP", 999999999.0);
0274     psd0.add<double>("multThresEB", EgammaLocalCovParamDefaults::kMultThresEB);
0275     psd0.add<double>("multThresEE", EgammaLocalCovParamDefaults::kMultThresEE);
0276     // preselection parameters
0277     desc.add<edm::ParameterSetDescription>("preselection", psd0);
0278   }
0279 
0280   // Corrections
0281   desc.add<std::string>("crackCorrectionFunction", "EcalClusterCrackCorrection");
0282 
0283   desc.add<bool>("ecalWeightsFromDB", true);
0284   desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightFiles", {})
0285       ->setComment("if not from DB. Otherwise, keep empty");
0286   desc.add<bool>("combinationWeightsFromDB", true);
0287   desc.add<std::vector<std::string>>("combinationRegressionWeightFile", {})
0288       ->setComment("if not from DB. Otherwise, keep empty");
0289 
0290   // regression. The labels are needed in all cases.
0291   desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightLabels", {});
0292   desc.add<std::vector<std::string>>("combinationRegressionWeightLabels", {});
0293 
0294   desc.add<std::vector<std::string>>(
0295       "ElecMVAFilesString",
0296       {
0297           "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_10_17Feb2011.weights.xml",
0298           "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_12_17Feb2011.weights.xml",
0299           "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_20_17Feb2011.weights.xml",
0300           "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_22_17Feb2011.weights.xml",
0301       });
0302   desc.add<std::vector<std::string>>(
0303       "SoftElecMVAFilesString",
0304       {
0305           "RecoEgamma/ElectronIdentification/data/TMVA_BDTSoftElectrons_7Feb2014.weights.xml",
0306       });
0307 
0308   {
0309     edm::ParameterSetDescription psd1;
0310     psd1.add<bool>("enabled", false);
0311     psd1.add<double>("extetaboundary", 2.65);
0312     psd1.add<std::string>("inputTensorName", "FirstLayer_input");
0313     psd1.add<std::string>("outputTensorName", "sequential/FinalLayer/Softmax");
0314 
0315     psd1.add<std::vector<std::string>>(
0316         "modelsFiles",
0317         {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_modelDNN.pb",
0318          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_modelDNN.pb",
0319          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_modelDNN.pb",
0320          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/modelDNN.pb",
0321          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/modelDNN.pb"});
0322     psd1.add<std::vector<std::string>>(
0323         "scalersFiles",
0324         {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_scaler.txt",
0325          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_scaler.txt",
0326          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_scaler.txt",
0327          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/scaler.txt",
0328          "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/scaler.txt"});
0329     psd1.add<std::vector<unsigned int>>("outputDim",  //Number of output nodes for the above models
0330                                         {5, 5, 5, 5, 3});
0331 
0332     psd1.add<bool>("useEBModelInGap", true);
0333     // preselection parameters
0334     desc.add<edm::ParameterSetDescription>("EleDNNPFid", psd1);
0335   }
0336 
0337   ///For PF cluster isolations
0338   ///ECAL
0339   {
0340     edm::ParameterSetDescription psd0;
0341     psd0.add<edm::InputTag>("pfClusterProducer", edm::InputTag("particleFlowClusterECAL"));
0342     psd0.add<double>("drMax", 0.3);
0343     psd0.add<double>("drVetoBarrel", 0.0);
0344     psd0.add<double>("drVetoEndcap", 0.0);
0345     psd0.add<double>("etaStripBarrel", 0.0);
0346     psd0.add<double>("etaStripEndcap", 0.0);
0347     psd0.add<double>("energyBarrel", 0.0);
0348     psd0.add<double>("energyEndcap", 0.0);
0349     desc.add<edm::ParameterSetDescription>("pfECALClusIsolCfg", psd0);
0350   }
0351 
0352   ///HCAL
0353   {
0354     edm::ParameterSetDescription psd0;
0355     psd0.add<edm::InputTag>("pfClusterProducerHCAL", edm::InputTag("particleFlowClusterHCAL"));
0356     psd0.add<edm::InputTag>("pfClusterProducerHFEM", edm::InputTag(""));
0357     psd0.add<edm::InputTag>("pfClusterProducerHFHAD", edm::InputTag(""));
0358     psd0.add<bool>("useHF", false);
0359     psd0.add<double>("drMax", 0.3);
0360     psd0.add<double>("drVetoBarrel", 0.0);
0361     psd0.add<double>("drVetoEndcap", 0.0);
0362     psd0.add<double>("etaStripBarrel", 0.0);
0363     psd0.add<double>("etaStripEndcap", 0.0);
0364     psd0.add<double>("energyBarrel", 0.0);
0365     psd0.add<double>("energyEndcap", 0.0);
0366     psd0.add<bool>("useEt", true);
0367     desc.add<edm::ParameterSetDescription>("pfHCALClusIsolCfg", psd0);
0368   }
0369 
0370   descriptions.add("gsfElectronProducerDefault", desc);
0371 }
0372 
0373 namespace {
0374   GsfElectronAlgo::CutsConfiguration makeCutsConfiguration(edm::ParameterSet const& pset) {
0375     return GsfElectronAlgo::CutsConfiguration{
0376         .minSCEtBarrel = pset.getParameter<double>("minSCEtBarrel"),
0377         .minSCEtEndcaps = pset.getParameter<double>("minSCEtEndcaps"),
0378         .maxEOverPBarrel = pset.getParameter<double>("maxEOverPBarrel"),
0379         .maxEOverPEndcaps = pset.getParameter<double>("maxEOverPEndcaps"),
0380         .minEOverPBarrel = pset.getParameter<double>("minEOverPBarrel"),
0381         .minEOverPEndcaps = pset.getParameter<double>("minEOverPEndcaps"),
0382         .maxHOverEBarrelCone = pset.getParameter<double>("maxHOverEBarrelCone"),
0383         .maxHOverEEndcapsCone = pset.getParameter<double>("maxHOverEEndcapsCone"),
0384         .maxHBarrelCone = pset.getParameter<double>("maxHBarrelCone"),
0385         .maxHEndcapsCone = pset.getParameter<double>("maxHEndcapsCone"),
0386         .maxHOverEBarrelBc = pset.getParameter<double>("maxHOverEBarrelBc"),
0387         .maxHOverEEndcapsBc = pset.getParameter<double>("maxHOverEEndcapsBc"),
0388         .maxHBarrelBc = pset.getParameter<double>("maxHBarrelBc"),
0389         .maxHEndcapsBc = pset.getParameter<double>("maxHEndcapsBc"),
0390         .maxDeltaEtaBarrel = pset.getParameter<double>("maxDeltaEtaBarrel"),
0391         .maxDeltaEtaEndcaps = pset.getParameter<double>("maxDeltaEtaEndcaps"),
0392         .maxDeltaPhiBarrel = pset.getParameter<double>("maxDeltaPhiBarrel"),
0393         .maxDeltaPhiEndcaps = pset.getParameter<double>("maxDeltaPhiEndcaps"),
0394         .maxSigmaIetaIetaBarrel = pset.getParameter<double>("maxSigmaIetaIetaBarrel"),
0395         .maxSigmaIetaIetaEndcaps = pset.getParameter<double>("maxSigmaIetaIetaEndcaps"),
0396         .maxFbremBarrel = pset.getParameter<double>("maxFbremBarrel"),
0397         .maxFbremEndcaps = pset.getParameter<double>("maxFbremEndcaps"),
0398         .isBarrel = pset.getParameter<bool>("isBarrel"),
0399         .isEndcaps = pset.getParameter<bool>("isEndcaps"),
0400         .isFiducial = pset.getParameter<bool>("isFiducial"),
0401         .maxTIP = pset.getParameter<double>("maxTIP"),
0402         .seedFromTEC = pset.getParameter<bool>("seedFromTEC"),
0403         .multThresEB = pset.getParameter<double>("multThresEB"),
0404         .multThresEE = pset.getParameter<double>("multThresEE"),
0405     };
0406   }
0407 };  // namespace
0408 
0409 void GsfElectronProducer::beginRun(const edm::Run& run, const edm::EventSetup& setup) {
0410   if (cutsFromDB) {
0411     hcalCuts = &setup.getData(hcalCutsToken_);
0412   }
0413 }
0414 
0415 GsfElectronProducer::GsfElectronProducer(const edm::ParameterSet& cfg, const GsfElectronAlgo::HeavyObjectCache* gcache)
0416     : cutsCfg_{makeCutsConfiguration(cfg.getParameter<edm::ParameterSet>("preselection"))},
0417       ecalSeedingParametersChecked_(false),
0418       electronPutToken_(produces<GsfElectronCollection>()),
0419       gsfPfRecTracksTag_(consumes(cfg.getParameter<edm::InputTag>("gsfPfRecTracksTag"))),
0420       useGsfPfRecTracks_(cfg.getParameter<bool>("useGsfPfRecTracks")),
0421       resetMvaValuesUsingPFCandidates_(cfg.getParameter<bool>("resetMvaValuesUsingPFCandidates")) {
0422   if (resetMvaValuesUsingPFCandidates_) {
0423     egmPFCandidateCollection_ = consumes(cfg.getParameter<edm::InputTag>("egmPFCandidatesTag"));
0424   }
0425 
0426   //Retrieve HCAL PF thresholds - from config or from DB
0427   cutsFromDB = cfg.getParameter<bool>("usePFThresholdsFromDB");
0428   if (cutsFromDB) {
0429     hcalCutsToken_ = esConsumes<HcalPFCuts, HcalPFCutsRcd, edm::Transition::BeginRun>(edm::ESInputTag("", "withTopo"));
0430   }
0431 
0432   inputCfg_.gsfElectronCores = consumes(cfg.getParameter<edm::InputTag>("gsfElectronCoresTag"));
0433   inputCfg_.hbheRecHitsTag = consumes(cfg.getParameter<edm::InputTag>("hbheRecHits"));
0434   inputCfg_.barrelRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("barrelRecHitCollectionTag"));
0435   inputCfg_.endcapRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("endcapRecHitCollectionTag"));
0436   inputCfg_.ctfTracks = consumes(cfg.getParameter<edm::InputTag>("ctfTracksTag"));
0437   // used to check config consistency with seeding
0438   inputCfg_.seedsTag = consumes(cfg.getParameter<edm::InputTag>("seedsTag"));
0439   inputCfg_.beamSpotTag = consumes(cfg.getParameter<edm::InputTag>("beamSpotTag"));
0440   inputCfg_.vtxCollectionTag = consumes(cfg.getParameter<edm::InputTag>("vtxTag"));
0441   if (cfg.getParameter<bool>("fillConvVtxFitProb"))
0442     inputCfg_.conversions = consumes(cfg.getParameter<edm::InputTag>("conversionsTag"));
0443 
0444   // inputs for PFCluster isolation
0445   const edm::ParameterSet& pfECALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfECALClusIsolCfg");
0446   const edm::ParameterSet& pfHCALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfHCALClusIsolCfg");
0447   inputCfg_.pfClusterProducer =
0448       consumes<reco::PFClusterCollection>(pfECALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducer"));
0449   inputCfg_.pfClusterProducerHCAL = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHCAL"));
0450   inputCfg_.pfClusterProducerHFEM = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFEM"));
0451   inputCfg_.pfClusterProducerHFHAD = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFHAD"));
0452 
0453   // Config for PFID dnn
0454   const auto& pset_dnn = cfg.getParameter<edm::ParameterSet>("EleDNNPFid");
0455   dnnPFidEnabled_ = pset_dnn.getParameter<bool>("enabled");
0456   extetaboundary_ = pset_dnn.getParameter<double>("extetaboundary");
0457 
0458   strategyCfg_.useDefaultEnergyCorrection = cfg.getParameter<bool>("useDefaultEnergyCorrection");
0459 
0460   strategyCfg_.applyPreselection = cfg.getParameter<bool>("applyPreselection");
0461   strategyCfg_.ecalDrivenEcalEnergyFromClassBasedParameterization =
0462       cfg.getParameter<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization");
0463   strategyCfg_.ecalDrivenEcalErrorFromClassBasedParameterization =
0464       cfg.getParameter<bool>("ecalDrivenEcalErrorFromClassBasedParameterization");
0465   strategyCfg_.pureTrackerDrivenEcalErrorFromSimpleParameterization =
0466       cfg.getParameter<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization");
0467   strategyCfg_.applyAmbResolution = cfg.getParameter<bool>("applyAmbResolution");
0468   strategyCfg_.ignoreNotPreselected = cfg.getParameter<bool>("ignoreNotPreselected");
0469   strategyCfg_.ambSortingStrategy = cfg.getParameter<unsigned>("ambSortingStrategy");
0470   strategyCfg_.ambClustersOverlapStrategy = cfg.getParameter<unsigned>("ambClustersOverlapStrategy");
0471   strategyCfg_.ctfTracksCheck = cfg.getParameter<bool>("ctfTracksCheck");
0472   strategyCfg_.PreSelectMVA = cfg.getParameter<double>("PreSelectMVA");
0473   strategyCfg_.MaxElePtForOnlyMVA = cfg.getParameter<double>("MaxElePtForOnlyMVA");
0474   strategyCfg_.useEcalRegression = cfg.getParameter<bool>("useEcalRegression");
0475   strategyCfg_.useCombinationRegression = cfg.getParameter<bool>("useCombinationRegression");
0476   strategyCfg_.fillConvVtxFitProb = cfg.getParameter<bool>("fillConvVtxFitProb");
0477   strategyCfg_.computePfClusterIso = dnnPFidEnabled_;
0478 
0479   // hcal helpers
0480   auto const& psetPreselection = cfg.getParameter<edm::ParameterSet>("preselection");
0481   hcalCfg_.hOverEConeSize = psetPreselection.getParameter<double>("hOverEConeSize");
0482   if (hcalCfg_.hOverEConeSize > 0) {
0483     hcalCfg_.onlyBehindCluster = false;
0484     hcalCfg_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
0485 
0486     //hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
0487     hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
0488 
0489     hcalCfg_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
0490     hcalCfg_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
0491     hcalCfg_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
0492     hcalCfg_.maxSeverityHE = hcalCfg_.maxSeverityHB;
0493   }
0494 
0495   hcalCfgBc_.hOverEConeSize = 0.;
0496   hcalCfgBc_.onlyBehindCluster = true;
0497   hcalCfgBc_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
0498 
0499   //hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
0500   hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
0501 
0502   hcalCfgBc_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
0503   hcalCfgBc_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
0504   hcalCfgBc_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
0505   hcalCfgBc_.maxSeverityHE = hcalCfgBc_.maxSeverityHB;
0506 
0507   hcalRun2EffDepth_ = cfg.getParameter<bool>("hcalRun2EffDepth");
0508 
0509   // Ecal rec hits configuration
0510   GsfElectronAlgo::EcalRecHitsConfiguration recHitsCfg;
0511   auto const& flagnamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
0512   recHitsCfg.recHitFlagsToBeExcludedBarrel = StringToEnumValue<EcalRecHit::Flags>(flagnamesbarrel);
0513   auto const& flagnamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
0514   recHitsCfg.recHitFlagsToBeExcludedEndcaps = StringToEnumValue<EcalRecHit::Flags>(flagnamesendcaps);
0515   auto const& severitynamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
0516   recHitsCfg.recHitSeverityToBeExcludedBarrel =
0517       StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesbarrel);
0518   auto const& severitynamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
0519   recHitsCfg.recHitSeverityToBeExcludedEndcaps =
0520       StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesendcaps);
0521 
0522   // isolation
0523   const GsfElectronAlgo::IsolationConfiguration isoCfg{
0524       .intRadiusHcal = cfg.getParameter<double>("intRadiusHcal"),
0525       .etMinHcal = cfg.getParameter<double>("etMinHcal"),
0526       .intRadiusEcalBarrel = cfg.getParameter<double>("intRadiusEcalBarrel"),
0527       .intRadiusEcalEndcaps = cfg.getParameter<double>("intRadiusEcalEndcaps"),
0528       .jurassicWidth = cfg.getParameter<double>("jurassicWidth"),
0529       .etMinBarrel = cfg.getParameter<double>("etMinBarrel"),
0530       .eMinBarrel = cfg.getParameter<double>("eMinBarrel"),
0531       .etMinEndcaps = cfg.getParameter<double>("etMinEndcaps"),
0532       .eMinEndcaps = cfg.getParameter<double>("eMinEndcaps"),
0533       .vetoClustered = cfg.getParameter<bool>("vetoClustered"),
0534       .useNumCrystals = cfg.getParameter<bool>("useNumCrystals")};
0535 
0536   // isolation
0537   const GsfElectronAlgo::PFClusterIsolationConfiguration pfisoCfg{
0538       .ecaldrMax = pfECALClusIsolCfg.getParameter<double>("drMax"),
0539       .ecaldrVetoBarrel = pfECALClusIsolCfg.getParameter<double>("drVetoBarrel"),
0540       .ecaldrVetoEndcap = pfECALClusIsolCfg.getParameter<double>("drVetoEndcap"),
0541       .ecaletaStripBarrel = pfECALClusIsolCfg.getParameter<double>("etaStripBarrel"),
0542       .ecaletaStripEndcap = pfECALClusIsolCfg.getParameter<double>("etaStripEndcap"),
0543       .ecalenergyBarrel = pfECALClusIsolCfg.getParameter<double>("energyBarrel"),
0544       .ecalenergyEndcap = pfECALClusIsolCfg.getParameter<double>("energyEndcap"),
0545       .useHF = pfHCALClusIsolCfg.getParameter<bool>("useHF"),
0546       .hcaldrMax = pfHCALClusIsolCfg.getParameter<double>("drMax"),
0547       .hcaldrVetoBarrel = pfHCALClusIsolCfg.getParameter<double>("drVetoBarrel"),
0548       .hcaldrVetoEndcap = pfHCALClusIsolCfg.getParameter<double>("drVetoEndcap"),
0549       .hcaletaStripBarrel = pfHCALClusIsolCfg.getParameter<double>("etaStripBarrel"),
0550       .hcaletaStripEndcap = pfHCALClusIsolCfg.getParameter<double>("etaStripEndcap"),
0551       .hcalenergyBarrel = pfHCALClusIsolCfg.getParameter<double>("energyBarrel"),
0552       .hcalenergyEndcap = pfHCALClusIsolCfg.getParameter<double>("energyEndcap"),
0553       .hcaluseEt = pfHCALClusIsolCfg.getParameter<bool>("useEt")};
0554 
0555   const RegressionHelper::Configuration regressionCfg{
0556       .ecalRegressionWeightLabels = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightLabels"),
0557       .ecalWeightsFromDB = cfg.getParameter<bool>("ecalWeightsFromDB"),
0558       .ecalRegressionWeightFiles = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightFiles"),
0559       .combinationRegressionWeightLabels =
0560           cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightLabels"),
0561       .combinationWeightsFromDB = cfg.getParameter<bool>("combinationWeightsFromDB"),
0562       .combinationRegressionWeightFiles =
0563           cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightFile")};
0564 
0565   // create algo
0566   algo_ = std::make_unique<GsfElectronAlgo>(
0567       inputCfg_,
0568       strategyCfg_,
0569       cutsCfg_,
0570       hcalCfg_,
0571       hcalCfgBc_,
0572       isoCfg,
0573       pfisoCfg,
0574       recHitsCfg,
0575       EcalClusterFunctionFactory::get()->create(
0576           cfg.getParameter<std::string>("crackCorrectionFunction"), cfg, consumesCollector()),
0577       regressionCfg,
0578       cfg.getParameter<edm::ParameterSet>("trkIsol03Cfg"),
0579       cfg.getParameter<edm::ParameterSet>("trkIsol04Cfg"),
0580       cfg.getParameter<edm::ParameterSet>("trkIsolHEEP03Cfg"),
0581       cfg.getParameter<edm::ParameterSet>("trkIsolHEEP04Cfg"),
0582       consumesCollector());
0583 
0584   if (dnnPFidEnabled_) {
0585     tfSessions_ = gcache->iElectronDNNEstimator->getSessions();
0586   }
0587 }
0588 
0589 void GsfElectronProducer::endStream() {
0590   for (auto session : tfSessions_) {
0591     tensorflow::closeSession(session);
0592   }
0593 }
0594 
0595 void GsfElectronProducer::checkEcalSeedingParameters(edm::ParameterSet const& pset) {
0596   if (!pset.exists("SeedConfiguration")) {
0597     return;
0598   }
0599   edm::ParameterSet seedConfiguration = pset.getParameter<edm::ParameterSet>("SeedConfiguration");
0600 
0601   if (seedConfiguration.getParameter<bool>("applyHOverECut")) {
0602     if ((hcalCfg_.hOverEConeSize != 0) &&
0603         (hcalCfg_.hOverEConeSize != seedConfiguration.getParameter<double>("hOverEConeSize"))) {
0604       edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
0605           << "The H/E cone size (" << hcalCfg_.hOverEConeSize << ") is different from ecal seeding ("
0606           << seedConfiguration.getParameter<double>("hOverEConeSize") << ").";
0607     }
0608     if (cutsCfg_.maxHOverEBarrelCone < seedConfiguration.getParameter<double>("maxHOverEBarrel")) {
0609       edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
0610           << "The max barrel cone H/E is lower than during ecal seeding.";
0611     }
0612     if (cutsCfg_.maxHOverEEndcapsCone < seedConfiguration.getParameter<double>("maxHOverEEndcaps")) {
0613       edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
0614           << "The max endcaps cone H/E is lower than during ecal seeding.";
0615     }
0616   }
0617 
0618   if (cutsCfg_.minSCEtBarrel < seedConfiguration.getParameter<double>("SCEtCut")) {
0619     edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
0620         << "The minimum super-cluster Et in barrel is lower than during ecal seeding.";
0621   }
0622   if (cutsCfg_.minSCEtEndcaps < seedConfiguration.getParameter<double>("SCEtCut")) {
0623     edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
0624         << "The minimum super-cluster Et in endcaps is lower than during ecal seeding.";
0625   }
0626 }
0627 
0628 //=======================================================================================
0629 // Ambiguity solving
0630 //=======================================================================================
0631 
0632 void GsfElectronProducer::setAmbiguityData(reco::GsfElectronCollection& electrons,
0633                                            edm::Event const& event,
0634                                            bool ignoreNotPreselected) const {
0635   // Getting required event data
0636   auto const& beamspot = event.get(inputCfg_.beamSpotTag);
0637   auto gsfPfRecTracks =
0638       useGsfPfRecTracks_ ? event.getHandle(gsfPfRecTracksTag_) : edm::Handle<reco::GsfPFRecTrackCollection>{};
0639   auto const& barrelRecHits = event.get(inputCfg_.barrelRecHitCollection);
0640   auto const& endcapRecHits = event.get(inputCfg_.endcapRecHitCollection);
0641 
0642   if (strategyCfg_.ambSortingStrategy == 0) {
0643     std::sort(electrons.begin(), electrons.end(), egamma::isBetterElectron);
0644   } else if (strategyCfg_.ambSortingStrategy == 1) {
0645     std::sort(electrons.begin(), electrons.end(), egamma::isInnermostElectron);
0646   } else {
0647     throw cms::Exception("GsfElectronAlgo|UnknownAmbiguitySortingStrategy")
0648         << "value of strategyCfg_.ambSortingStrategy is : " << strategyCfg_.ambSortingStrategy;
0649   }
0650 
0651   // init
0652   for (auto& electron : electrons) {
0653     electron.clearAmbiguousGsfTracks();
0654     electron.setAmbiguous(false);
0655   }
0656 
0657   // get ambiguous from GsfPfRecTracks
0658   if (useGsfPfRecTracks_) {
0659     for (auto& e1 : electrons) {
0660       bool found = false;
0661       for (auto const& gsfPfRecTrack : *gsfPfRecTracks) {
0662         if (gsfPfRecTrack.gsfTrackRef() == e1.gsfTrack()) {
0663           if (found) {
0664             edm::LogWarning("GsfElectronAlgo") << "associated gsfPfRecTrack already found";
0665           } else {
0666             found = true;
0667             for (auto const& duplicate : gsfPfRecTrack.convBremGsfPFRecTrackRef()) {
0668               e1.addAmbiguousGsfTrack(duplicate->gsfTrackRef());
0669             }
0670           }
0671         }
0672       }
0673     }
0674   }
0675   // or search overlapping clusters
0676   else {
0677     for (auto e1 = electrons.begin(); e1 != electrons.end(); ++e1) {
0678       if (e1->ambiguous())
0679         continue;
0680       if (ignoreNotPreselected && !isPreselected(*e1))
0681         continue;
0682 
0683       SuperClusterRef scRef1 = e1->superCluster();
0684       CaloClusterPtr eleClu1 = e1->electronCluster();
0685       LogDebug("GsfElectronAlgo") << "Blessing electron with E/P " << e1->eSuperClusterOverP() << ", cluster "
0686                                   << scRef1.get() << " & track " << e1->gsfTrack().get();
0687 
0688       for (auto e2 = e1 + 1; e2 != electrons.end(); ++e2) {
0689         if (e2->ambiguous())
0690           continue;
0691         if (ignoreNotPreselected && !isPreselected(*e2))
0692           continue;
0693 
0694         SuperClusterRef scRef2 = e2->superCluster();
0695         CaloClusterPtr eleClu2 = e2->electronCluster();
0696 
0697         // search if same cluster
0698         bool sameCluster = false;
0699         if (strategyCfg_.ambClustersOverlapStrategy == 0) {
0700           sameCluster = (scRef1 == scRef2);
0701         } else if (strategyCfg_.ambClustersOverlapStrategy == 1) {
0702           float eMin = 1.;
0703           float threshold = eMin * cosh(EleRelPoint(scRef1->position(), beamspot.position()).eta());
0704           using egamma::sharedEnergy;
0705           sameCluster = ((sharedEnergy(*eleClu1, *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
0706                          (sharedEnergy(*scRef1->seed(), *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
0707                          (sharedEnergy(*eleClu1, *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold) ||
0708                          (sharedEnergy(*scRef1->seed(), *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold));
0709         } else {
0710           throw cms::Exception("GsfElectronAlgo|UnknownAmbiguityClustersOverlapStrategy")
0711               << "value of strategyCfg_.ambClustersOverlapStrategy is : " << strategyCfg_.ambClustersOverlapStrategy;
0712         }
0713 
0714         // main instructions
0715         if (sameCluster) {
0716           LogDebug("GsfElectronAlgo") << "Discarding electron with E/P " << e2->eSuperClusterOverP() << ", cluster "
0717                                       << scRef2.get() << " and track " << e2->gsfTrack().get();
0718           e1->addAmbiguousGsfTrack(e2->gsfTrack());
0719           e2->setAmbiguous(true);
0720         } else if (e1->gsfTrack() == e2->gsfTrack()) {
0721           edm::LogWarning("GsfElectronAlgo") << "Forgetting electron with E/P " << e2->eSuperClusterOverP()
0722                                              << ", cluster " << scRef2.get() << " and track " << e2->gsfTrack().get();
0723           e2->setAmbiguous(true);
0724         }
0725       }
0726     }
0727   }
0728 }
0729 
0730 bool GsfElectronProducer::isPreselected(GsfElectron const& ele) const {
0731   bool passCutBased = ele.passingCutBasedPreselection();
0732   bool passPF = ele.passingPflowPreselection();
0733   // it is worth nothing for gedGsfElectrons, this does nothing as its not set
0734   // till GedGsfElectron finaliser, this is always false
0735   bool passmva = ele.passingMvaPreselection();
0736   if (!ele.ecalDrivenSeed()) {
0737     if (ele.pt() > strategyCfg_.MaxElePtForOnlyMVA)
0738       return passmva && passCutBased;
0739     else
0740       return passmva;
0741   } else {
0742     return passCutBased || passPF || passmva;
0743   }
0744 }
0745 
0746 // ------------ method called to produce the data  ------------
0747 void GsfElectronProducer::produce(edm::Event& event, const edm::EventSetup& setup) {
0748   // check configuration
0749   if (!ecalSeedingParametersChecked_) {
0750     ecalSeedingParametersChecked_ = true;
0751     auto seeds = event.getHandle(inputCfg_.seedsTag);
0752     if (!seeds.isValid()) {
0753       edm::LogWarning("GsfElectronAlgo|UnreachableSeedsProvenance")
0754           << "Cannot check consistency of parameters with ecal seeding ones,"
0755           << " because the original collection of seeds is not any more available.";
0756     } else {
0757       checkEcalSeedingParameters(edm::parameterSet(seeds.provenance()->stable(), event.processHistory()));
0758     }
0759   }
0760 
0761   auto electrons = algo_->completeElectrons(event, setup, globalCache(), hcalCuts);
0762   if (resetMvaValuesUsingPFCandidates_) {
0763     const auto gsfMVAInputMap = matchWithPFCandidates(event.get(egmPFCandidateCollection_));
0764     for (auto& el : electrons) {
0765       el.setMvaInput(gsfMVAInputMap.find(el.gsfTrack())->second);  // set Run2 MVA inputs
0766     }
0767     setMVAOutputs(
0768         electrons, globalCache(), event.get(inputCfg_.vtxCollectionTag), dnnPFidEnabled_, extetaboundary_, tfSessions_);
0769   }
0770 
0771   // all electrons
0772   logElectrons(electrons, event, "GsfElectronAlgo Info (before preselection)");
0773   // preselection
0774   if (strategyCfg_.applyPreselection) {
0775     electrons.erase(
0776         std::remove_if(electrons.begin(), electrons.end(), [this](auto const& ele) { return !isPreselected(ele); }),
0777         electrons.end());
0778     logElectrons(electrons, event, "GsfElectronAlgo Info (after preselection)");
0779   }
0780   // ambiguity
0781   setAmbiguityData(electrons, event, strategyCfg_.ignoreNotPreselected);
0782   if (strategyCfg_.applyAmbResolution) {
0783     electrons.erase(std::remove_if(electrons.begin(), electrons.end(), std::mem_fn(&reco::GsfElectron::ambiguous)),
0784                     electrons.end());
0785     logElectrons(electrons, event, "GsfElectronAlgo Info (after amb. solving)");
0786   }
0787   // go back to run2-like 2 effective depths if desired - depth 1 is the normal depth 1, depth 2 is the sum over the rest
0788   if (hcalRun2EffDepth_) {
0789     for (auto& ele : electrons)
0790       ele.hcalToRun2EffDepth();
0791   }
0792   // final filling
0793   event.emplace(electronPutToken_, std::move(electrons));
0794 }
0795 
0796 #include "FWCore/Framework/interface/MakerMacros.h"
0797 DEFINE_FWK_MODULE(GsfElectronProducer);