CMS 3D CMS Logo

GsfElectronProducer.cc
Go to the documentation of this file.
27 
28 #include <array>
29 
30 using namespace reco;
31 
32 namespace {
33 
34  void setMVAOutputs(reco::GsfElectronCollection& electrons,
37  bool dnnPFidEnabled,
38  float extetaboundary,
39  const std::vector<tensorflow::Session*>& tfSessions) {
40  std::vector<GsfElectron::MvaOutput> mva_outputs(electrons.size());
41  size_t iele = 0;
42  for (auto& el : electrons) {
43  GsfElectron::MvaOutput mvaOutput;
44  mvaOutput.mva_e_pi = hoc->sElectronMVAEstimator->mva(el, vertices);
45  mvaOutput.mva_Isolated = hoc->iElectronMVAEstimator->mva(el, vertices.size());
46  if (dnnPFidEnabled) {
47  mva_outputs[iele] = mvaOutput;
48  } else {
49  el.setMvaOutput(mvaOutput);
50  }
51  iele++;
52  }
53  if (dnnPFidEnabled) {
54  // Here send the list of electrons to the ElectronDNNEstimator and get back the values for all the electrons in one go
55  LogDebug("GsfElectronProducer") << "Getting DNN PFId for ele";
56  const auto& dnn_ele_pfid = hoc->iElectronDNNEstimator->evaluate(electrons, tfSessions);
57  int jele = 0;
58  for (auto& el : electrons) {
59  const auto& [iModel, values] = dnn_ele_pfid[jele];
60  // get the previous values
61  auto& mvaOutput = mva_outputs[jele];
62 
63  if (iModel <= 3) { // models 0,1,2,3 have 5 outputs in this version
64  assert(values.size() == 5);
65  mvaOutput.dnn_e_sigIsolated = values[0];
66  mvaOutput.dnn_e_sigNonIsolated = values[1];
67  mvaOutput.dnn_e_bkgNonIsolated = values[2];
68  mvaOutput.dnn_e_bkgTau = values[3];
69  mvaOutput.dnn_e_bkgPhoton = values[4];
70  } else if (iModel == 4) { //etaExtended model has 3 outputs
71  assert(values.size() == 3);
72  mvaOutput.dnn_e_sigIsolated = values[0];
73  mvaOutput.dnn_e_sigNonIsolated = 0.0;
74  mvaOutput.dnn_e_bkgNonIsolated = values[1];
75  mvaOutput.dnn_e_bkgTau = 0.0;
76  mvaOutput.dnn_e_bkgPhoton = values[2];
77  }
78  el.setMvaOutput(mvaOutput);
79  jele++;
80  }
81  }
82  }
83 
84  // Something more clever has to be found. The collections are small, so the timing is not
85  // an issue here; but it is clearly suboptimal
86 
87  auto matchWithPFCandidates(std::vector<reco::PFCandidate> const& pfCandidates) {
88  std::map<reco::GsfTrackRef, reco::GsfElectron::MvaInput> gsfMVAInputs{};
89 
90  //Loop over the collection of PFFCandidates
91  for (auto const& pfCand : pfCandidates) {
93  // First check that the GsfTrack is non null
94  if (pfCand.gsfTrackRef().isNonnull()) {
96  input.earlyBrem = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_FirstBrem);
97  input.lateBrem = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_LateBrem);
98  input.deltaEta = pfCand.egammaExtraRef()->mvaVariable(reco::PFCandidateEGammaExtra::MVA_DeltaEtaTrackCluster);
99  input.sigmaEtaEta = pfCand.egammaExtraRef()->sigmaEtaEta();
100  input.hadEnergy = pfCand.egammaExtraRef()->hadEnergy();
101  gsfMVAInputs[pfCand.gsfTrackRef()] = input;
102  }
103  }
104  return gsfMVAInputs;
105  }
106 
107  void logElectrons(reco::GsfElectronCollection const& electrons, edm::Event const& event, const std::string& title) {
108  LogTrace("GsfElectronAlgo") << "========== " << title << " ==========";
109  LogTrace("GsfElectronAlgo") << "Event: " << event.id();
110  LogTrace("GsfElectronAlgo") << "Number of electrons: " << electrons.size();
111  for (auto const& ele : electrons) {
112  LogTrace("GsfElectronAlgo") << "Electron with charge, pt, eta, phi: " << ele.charge() << " , " << ele.pt()
113  << " , " << ele.eta() << " , " << ele.phi();
114  }
115  LogTrace("GsfElectronAlgo") << "=================================================";
116  }
117 
118 } // namespace
119 
120 class GsfElectronProducer : public edm::stream::EDProducer<edm::GlobalCache<GsfElectronAlgo::HeavyObjectCache>> {
121 public:
123 
125 
126  static std::unique_ptr<GsfElectronAlgo::HeavyObjectCache> initializeGlobalCache(const edm::ParameterSet& conf) {
127  return std::make_unique<GsfElectronAlgo::HeavyObjectCache>(conf);
128  }
129 
130  void endStream() override;
131 
133 
134  // ------------ method called to produce the data ------------
135  void produce(edm::Event& event, const edm::EventSetup& setup) override;
136 
137 private:
138  std::unique_ptr<GsfElectronAlgo> algo_;
139 
140  // configurables
145 
147 
148  bool isPreselected(reco::GsfElectron const& ele) const;
149  void setAmbiguityData(reco::GsfElectronCollection& electrons,
150  edm::Event const& event,
151  bool ignoreNotPreselected = true) const;
152 
153  // check expected configuration of previous modules
155  void checkEcalSeedingParameters(edm::ParameterSet const&);
156 
160 
161  const bool useGsfPfRecTracks_;
162 
164 
167 
168  std::vector<tensorflow::Session*> tfSessions_;
169 
172 };
173 
176  // input collections
177  desc.add<edm::InputTag>("gsfElectronCoresTag", {"ecalDrivenGsfElectronCores"});
178  desc.add<edm::InputTag>("vtxTag", {"offlinePrimaryVertices"});
179  desc.add<edm::InputTag>("conversionsTag", {"allConversions"});
180  desc.add<edm::InputTag>("gsfPfRecTracksTag", {"pfTrackElec"});
181  desc.add<edm::InputTag>("barrelRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEB"});
182  desc.add<edm::InputTag>("endcapRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEE"});
183  desc.add<edm::InputTag>("seedsTag", {"ecalDrivenElectronSeeds"});
184  desc.add<edm::InputTag>("beamSpotTag", {"offlineBeamSpot"});
185  desc.add<edm::InputTag>("egmPFCandidatesTag", {"particleFlowEGamma"});
186 
187  // steering
188  desc.add<bool>("useDefaultEnergyCorrection", true);
189  desc.add<bool>("useCombinationRegression", false);
190  desc.add<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization", true);
191  desc.add<bool>("ecalDrivenEcalErrorFromClassBasedParameterization", true);
192  desc.add<bool>("applyPreselection", false);
193  desc.add<bool>("useEcalRegression", false);
194  desc.add<bool>("applyAmbResolution", false);
195  desc.add<bool>("ignoreNotPreselected", true);
196  desc.add<bool>("useGsfPfRecTracks", true);
197  desc.add<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization", true);
198  desc.add<unsigned int>("ambSortingStrategy", 1);
199  desc.add<unsigned int>("ambClustersOverlapStrategy", 1);
200  desc.add<bool>("fillConvVtxFitProb", true);
201  desc.add<bool>("resetMvaValuesUsingPFCandidates", false);
202 
203  // Ecal rec hits configuration
204  desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
205  desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
206  desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
207  desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
208 
209  // Hcal rec hits configuration
210  desc.add<bool>("checkHcalStatus", true);
211  desc.add<edm::InputTag>("hbheRecHits", edm::InputTag("hbhereco"));
212  desc.add<std::vector<double>>("recHitEThresholdHB", {0., 0., 0., 0.});
213  desc.add<std::vector<double>>("recHitEThresholdHE", {0., 0., 0., 0., 0., 0., 0.});
214  desc.add<int>("maxHcalRecHitSeverity", 999999);
215  desc.add<bool>("hcalRun2EffDepth", false);
216  desc.add<bool>("usePFThresholdsFromDB", false);
217 
218  // Isolation algos configuration
219  desc.add("trkIsol03Cfg", EleTkIsolFromCands::pSetDescript());
220  desc.add("trkIsol04Cfg", EleTkIsolFromCands::pSetDescript());
221  desc.add("trkIsolHEEP03Cfg", EleTkIsolFromCands::pSetDescript());
222  desc.add("trkIsolHEEP04Cfg", EleTkIsolFromCands::pSetDescript());
223  desc.add<bool>("useNumCrystals", true);
224  desc.add<double>("etMinBarrel", 0.0);
225  desc.add<double>("etMinEndcaps", 0.11);
226  desc.add<double>("etMinHcal", 0.0);
227  desc.add<double>("eMinBarrel", 0.095);
228  desc.add<double>("eMinEndcaps", 0.0);
229  desc.add<double>("intRadiusEcalBarrel", 3.0);
230  desc.add<double>("intRadiusEcalEndcaps", 3.0);
231  desc.add<double>("intRadiusHcal", 0.15);
232  desc.add<double>("jurassicWidth", 1.5);
233  desc.add<bool>("vetoClustered", false);
234 
235  // backward compatibility mechanism for ctf tracks
236  desc.add<bool>("ctfTracksCheck", true);
237  desc.add<edm::InputTag>("ctfTracksTag", {"generalTracks"});
238 
239  desc.add<double>("MaxElePtForOnlyMVA", 50.0);
240  desc.add<double>("PreSelectMVA", -0.1);
241 
242  {
244  psd0.add<double>("minSCEtBarrel", 4.0);
245  psd0.add<double>("minSCEtEndcaps", 4.0);
246  psd0.add<double>("minEOverPBarrel", 0.0);
247  psd0.add<double>("minEOverPEndcaps", 0.0);
248  psd0.add<double>("maxEOverPBarrel", 999999999.0);
249  psd0.add<double>("maxEOverPEndcaps", 999999999.0);
250  psd0.add<double>("maxDeltaEtaBarrel", 0.02);
251  psd0.add<double>("maxDeltaEtaEndcaps", 0.02);
252  psd0.add<double>("maxDeltaPhiBarrel", 0.15);
253  psd0.add<double>("maxDeltaPhiEndcaps", 0.15);
254  psd0.add<double>("hOverEConeSize", 0.15);
255  psd0.add<double>("maxHOverEBarrelCone", 0.15);
256  psd0.add<double>("maxHOverEEndcapsCone", 0.15);
257  psd0.add<double>("maxHBarrelCone", 0.0);
258  psd0.add<double>("maxHEndcapsCone", 0.0);
259  psd0.add<double>("maxHOverEBarrelBc", 0.15);
260  psd0.add<double>("maxHOverEEndcapsBc", 0.15);
261  psd0.add<double>("maxHBarrelBc", 0.0);
262  psd0.add<double>("maxHEndcapsBc", 0.0);
263  psd0.add<double>("maxSigmaIetaIetaBarrel", 999999999.0);
264  psd0.add<double>("maxSigmaIetaIetaEndcaps", 999999999.0);
265  psd0.add<double>("maxFbremBarrel", 999999999.0);
266  psd0.add<double>("maxFbremEndcaps", 999999999.0);
267  psd0.add<bool>("isBarrel", false);
268  psd0.add<bool>("isEndcaps", false);
269  psd0.add<bool>("isFiducial", false);
270  psd0.add<bool>("seedFromTEC", true);
271  psd0.add<double>("maxTIP", 999999999.0);
272  psd0.add<double>("multThresEB", EgammaLocalCovParamDefaults::kMultThresEB);
273  psd0.add<double>("multThresEE", EgammaLocalCovParamDefaults::kMultThresEE);
274  // preselection parameters
275  desc.add<edm::ParameterSetDescription>("preselection", psd0);
276  }
277 
278  // Corrections
279  desc.add<std::string>("crackCorrectionFunction", "EcalClusterCrackCorrection");
280 
281  desc.add<bool>("ecalWeightsFromDB", true);
282  desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightFiles", {})
283  ->setComment("if not from DB. Otherwise, keep empty");
284  desc.add<bool>("combinationWeightsFromDB", true);
285  desc.add<std::vector<std::string>>("combinationRegressionWeightFile", {})
286  ->setComment("if not from DB. Otherwise, keep empty");
287 
288  // regression. The labels are needed in all cases.
289  desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightLabels", {});
290  desc.add<std::vector<std::string>>("combinationRegressionWeightLabels", {});
291 
292  desc.add<std::vector<std::string>>(
293  "ElecMVAFilesString",
294  {
295  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_10_17Feb2011.weights.xml",
296  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_12_17Feb2011.weights.xml",
297  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_20_17Feb2011.weights.xml",
298  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_22_17Feb2011.weights.xml",
299  });
300  desc.add<std::vector<std::string>>(
301  "SoftElecMVAFilesString",
302  {
303  "RecoEgamma/ElectronIdentification/data/TMVA_BDTSoftElectrons_7Feb2014.weights.xml",
304  });
305 
306  {
308  psd1.add<bool>("enabled", false);
309  psd1.add<double>("extetaboundary", 2.65);
310  psd1.add<std::string>("inputTensorName", "FirstLayer_input");
311  psd1.add<std::string>("outputTensorName", "sequential/FinalLayer/Softmax");
312 
313  psd1.add<std::vector<std::string>>(
314  "modelsFiles",
315  {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_modelDNN.pb",
316  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_modelDNN.pb",
317  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_modelDNN.pb",
318  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/modelDNN.pb",
319  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/modelDNN.pb"});
320  psd1.add<std::vector<std::string>>(
321  "scalersFiles",
322  {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_scaler.txt",
323  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_scaler.txt",
324  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_scaler.txt",
325  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/scaler.txt",
326  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/scaler.txt"});
327  psd1.add<std::vector<unsigned int>>("outputDim", //Number of output nodes for the above models
328  {5, 5, 5, 5, 3});
329 
330  psd1.add<bool>("useEBModelInGap", true);
331  // preselection parameters
332  desc.add<edm::ParameterSetDescription>("EleDNNPFid", psd1);
333  }
334 
337  {
339  psd0.add<edm::InputTag>("pfClusterProducer", edm::InputTag("particleFlowClusterECAL"));
340  psd0.add<double>("drMax", 0.3);
341  psd0.add<double>("drVetoBarrel", 0.0);
342  psd0.add<double>("drVetoEndcap", 0.0);
343  psd0.add<double>("etaStripBarrel", 0.0);
344  psd0.add<double>("etaStripEndcap", 0.0);
345  psd0.add<double>("energyBarrel", 0.0);
346  psd0.add<double>("energyEndcap", 0.0);
347  desc.add<edm::ParameterSetDescription>("pfECALClusIsolCfg", psd0);
348  }
349 
351  {
353  psd0.add<edm::InputTag>("pfClusterProducerHCAL", edm::InputTag("particleFlowClusterHCAL"));
354  psd0.add<edm::InputTag>("pfClusterProducerHFEM", edm::InputTag(""));
355  psd0.add<edm::InputTag>("pfClusterProducerHFHAD", edm::InputTag(""));
356  psd0.add<bool>("useHF", false);
357  psd0.add<double>("drMax", 0.3);
358  psd0.add<double>("drVetoBarrel", 0.0);
359  psd0.add<double>("drVetoEndcap", 0.0);
360  psd0.add<double>("etaStripBarrel", 0.0);
361  psd0.add<double>("etaStripEndcap", 0.0);
362  psd0.add<double>("energyBarrel", 0.0);
363  psd0.add<double>("energyEndcap", 0.0);
364  psd0.add<bool>("useEt", true);
365  desc.add<edm::ParameterSetDescription>("pfHCALClusIsolCfg", psd0);
366  }
367 
368  descriptions.add("gsfElectronProducerDefault", desc);
369 }
370 
371 namespace {
372  GsfElectronAlgo::CutsConfiguration makeCutsConfiguration(edm::ParameterSet const& pset) {
374  .minSCEtBarrel = pset.getParameter<double>("minSCEtBarrel"),
375  .minSCEtEndcaps = pset.getParameter<double>("minSCEtEndcaps"),
376  .maxEOverPBarrel = pset.getParameter<double>("maxEOverPBarrel"),
377  .maxEOverPEndcaps = pset.getParameter<double>("maxEOverPEndcaps"),
378  .minEOverPBarrel = pset.getParameter<double>("minEOverPBarrel"),
379  .minEOverPEndcaps = pset.getParameter<double>("minEOverPEndcaps"),
380  .maxHOverEBarrelCone = pset.getParameter<double>("maxHOverEBarrelCone"),
381  .maxHOverEEndcapsCone = pset.getParameter<double>("maxHOverEEndcapsCone"),
382  .maxHBarrelCone = pset.getParameter<double>("maxHBarrelCone"),
383  .maxHEndcapsCone = pset.getParameter<double>("maxHEndcapsCone"),
384  .maxHOverEBarrelBc = pset.getParameter<double>("maxHOverEBarrelBc"),
385  .maxHOverEEndcapsBc = pset.getParameter<double>("maxHOverEEndcapsBc"),
386  .maxHBarrelBc = pset.getParameter<double>("maxHBarrelBc"),
387  .maxHEndcapsBc = pset.getParameter<double>("maxHEndcapsBc"),
388  .maxDeltaEtaBarrel = pset.getParameter<double>("maxDeltaEtaBarrel"),
389  .maxDeltaEtaEndcaps = pset.getParameter<double>("maxDeltaEtaEndcaps"),
390  .maxDeltaPhiBarrel = pset.getParameter<double>("maxDeltaPhiBarrel"),
391  .maxDeltaPhiEndcaps = pset.getParameter<double>("maxDeltaPhiEndcaps"),
392  .maxSigmaIetaIetaBarrel = pset.getParameter<double>("maxSigmaIetaIetaBarrel"),
393  .maxSigmaIetaIetaEndcaps = pset.getParameter<double>("maxSigmaIetaIetaEndcaps"),
394  .maxFbremBarrel = pset.getParameter<double>("maxFbremBarrel"),
395  .maxFbremEndcaps = pset.getParameter<double>("maxFbremEndcaps"),
396  .isBarrel = pset.getParameter<bool>("isBarrel"),
397  .isEndcaps = pset.getParameter<bool>("isEndcaps"),
398  .isFiducial = pset.getParameter<bool>("isFiducial"),
399  .maxTIP = pset.getParameter<double>("maxTIP"),
400  .seedFromTEC = pset.getParameter<bool>("seedFromTEC"),
401  .multThresEB = pset.getParameter<double>("multThresEB"),
402  .multThresEE = pset.getParameter<double>("multThresEE"),
403  };
404  }
405 }; // namespace
406 
408  : cutsCfg_{makeCutsConfiguration(cfg.getParameter<edm::ParameterSet>("preselection"))},
409  ecalSeedingParametersChecked_(false),
410  electronPutToken_(produces<GsfElectronCollection>()),
411  gsfPfRecTracksTag_(consumes(cfg.getParameter<edm::InputTag>("gsfPfRecTracksTag"))),
412  useGsfPfRecTracks_(cfg.getParameter<bool>("useGsfPfRecTracks")),
413  resetMvaValuesUsingPFCandidates_(cfg.getParameter<bool>("resetMvaValuesUsingPFCandidates")) {
414  if (resetMvaValuesUsingPFCandidates_) {
415  egmPFCandidateCollection_ = consumes(cfg.getParameter<edm::InputTag>("egmPFCandidatesTag"));
416  }
417 
418  //Retrieve HCAL PF thresholds - from config or from DB
419  cutsFromDB_ = cfg.getParameter<bool>("usePFThresholdsFromDB");
420  if (cutsFromDB_) {
421  hcalCutsToken_ = esConsumes<HcalPFCuts, HcalPFCutsRcd>(edm::ESInputTag("", "withTopo"));
422  }
423 
424  inputCfg_.gsfElectronCores = consumes(cfg.getParameter<edm::InputTag>("gsfElectronCoresTag"));
425  inputCfg_.hbheRecHitsTag = consumes(cfg.getParameter<edm::InputTag>("hbheRecHits"));
426  inputCfg_.barrelRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("barrelRecHitCollectionTag"));
427  inputCfg_.endcapRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("endcapRecHitCollectionTag"));
428  inputCfg_.ctfTracks = consumes(cfg.getParameter<edm::InputTag>("ctfTracksTag"));
429  // used to check config consistency with seeding
430  inputCfg_.seedsTag = consumes(cfg.getParameter<edm::InputTag>("seedsTag"));
431  inputCfg_.beamSpotTag = consumes(cfg.getParameter<edm::InputTag>("beamSpotTag"));
432  inputCfg_.vtxCollectionTag = consumes(cfg.getParameter<edm::InputTag>("vtxTag"));
433  if (cfg.getParameter<bool>("fillConvVtxFitProb"))
434  inputCfg_.conversions = consumes(cfg.getParameter<edm::InputTag>("conversionsTag"));
435 
436  // inputs for PFCluster isolation
437  const edm::ParameterSet& pfECALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfECALClusIsolCfg");
438  const edm::ParameterSet& pfHCALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfHCALClusIsolCfg");
439  inputCfg_.pfClusterProducer =
440  consumes<reco::PFClusterCollection>(pfECALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducer"));
441  inputCfg_.pfClusterProducerHCAL = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHCAL"));
442  inputCfg_.pfClusterProducerHFEM = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFEM"));
443  inputCfg_.pfClusterProducerHFHAD = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFHAD"));
444 
445  // Config for PFID dnn
446  const auto& pset_dnn = cfg.getParameter<edm::ParameterSet>("EleDNNPFid");
447  dnnPFidEnabled_ = pset_dnn.getParameter<bool>("enabled");
448  extetaboundary_ = pset_dnn.getParameter<double>("extetaboundary");
449 
450  strategyCfg_.useDefaultEnergyCorrection = cfg.getParameter<bool>("useDefaultEnergyCorrection");
451 
452  strategyCfg_.applyPreselection = cfg.getParameter<bool>("applyPreselection");
453  strategyCfg_.ecalDrivenEcalEnergyFromClassBasedParameterization =
454  cfg.getParameter<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization");
455  strategyCfg_.ecalDrivenEcalErrorFromClassBasedParameterization =
456  cfg.getParameter<bool>("ecalDrivenEcalErrorFromClassBasedParameterization");
457  strategyCfg_.pureTrackerDrivenEcalErrorFromSimpleParameterization =
458  cfg.getParameter<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization");
459  strategyCfg_.applyAmbResolution = cfg.getParameter<bool>("applyAmbResolution");
460  strategyCfg_.ignoreNotPreselected = cfg.getParameter<bool>("ignoreNotPreselected");
461  strategyCfg_.ambSortingStrategy = cfg.getParameter<unsigned>("ambSortingStrategy");
462  strategyCfg_.ambClustersOverlapStrategy = cfg.getParameter<unsigned>("ambClustersOverlapStrategy");
463  strategyCfg_.ctfTracksCheck = cfg.getParameter<bool>("ctfTracksCheck");
464  strategyCfg_.PreSelectMVA = cfg.getParameter<double>("PreSelectMVA");
465  strategyCfg_.MaxElePtForOnlyMVA = cfg.getParameter<double>("MaxElePtForOnlyMVA");
466  strategyCfg_.useEcalRegression = cfg.getParameter<bool>("useEcalRegression");
467  strategyCfg_.useCombinationRegression = cfg.getParameter<bool>("useCombinationRegression");
468  strategyCfg_.fillConvVtxFitProb = cfg.getParameter<bool>("fillConvVtxFitProb");
469  strategyCfg_.computePfClusterIso = dnnPFidEnabled_;
470 
471  // hcal helpers
472  auto const& psetPreselection = cfg.getParameter<edm::ParameterSet>("preselection");
473  hcalCfg_.hOverEConeSize = psetPreselection.getParameter<double>("hOverEConeSize");
474  if (hcalCfg_.hOverEConeSize > 0) {
475  hcalCfg_.onlyBehindCluster = false;
476  hcalCfg_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
477 
478  //hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
479  hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
480 
481  hcalCfg_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
482  hcalCfg_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
483  hcalCfg_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
484  hcalCfg_.maxSeverityHE = hcalCfg_.maxSeverityHB;
485  }
486 
487  hcalCfgBc_.hOverEConeSize = 0.;
488  hcalCfgBc_.onlyBehindCluster = true;
489  hcalCfgBc_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
490 
491  //hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
492  hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
493 
494  hcalCfgBc_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
495  hcalCfgBc_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
496  hcalCfgBc_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
497  hcalCfgBc_.maxSeverityHE = hcalCfgBc_.maxSeverityHB;
498 
499  hcalRun2EffDepth_ = cfg.getParameter<bool>("hcalRun2EffDepth");
500 
501  // Ecal rec hits configuration
503  auto const& flagnamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
504  recHitsCfg.recHitFlagsToBeExcludedBarrel = StringToEnumValue<EcalRecHit::Flags>(flagnamesbarrel);
505  auto const& flagnamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
506  recHitsCfg.recHitFlagsToBeExcludedEndcaps = StringToEnumValue<EcalRecHit::Flags>(flagnamesendcaps);
507  auto const& severitynamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
508  recHitsCfg.recHitSeverityToBeExcludedBarrel =
509  StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesbarrel);
510  auto const& severitynamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
511  recHitsCfg.recHitSeverityToBeExcludedEndcaps =
512  StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesendcaps);
513 
514  // isolation
516  .intRadiusHcal = cfg.getParameter<double>("intRadiusHcal"),
517  .etMinHcal = cfg.getParameter<double>("etMinHcal"),
518  .intRadiusEcalBarrel = cfg.getParameter<double>("intRadiusEcalBarrel"),
519  .intRadiusEcalEndcaps = cfg.getParameter<double>("intRadiusEcalEndcaps"),
520  .jurassicWidth = cfg.getParameter<double>("jurassicWidth"),
521  .etMinBarrel = cfg.getParameter<double>("etMinBarrel"),
522  .eMinBarrel = cfg.getParameter<double>("eMinBarrel"),
523  .etMinEndcaps = cfg.getParameter<double>("etMinEndcaps"),
524  .eMinEndcaps = cfg.getParameter<double>("eMinEndcaps"),
525  .vetoClustered = cfg.getParameter<bool>("vetoClustered"),
526  .useNumCrystals = cfg.getParameter<bool>("useNumCrystals")};
527 
528  // isolation
530  .ecaldrMax = pfECALClusIsolCfg.getParameter<double>("drMax"),
531  .ecaldrVetoBarrel = pfECALClusIsolCfg.getParameter<double>("drVetoBarrel"),
532  .ecaldrVetoEndcap = pfECALClusIsolCfg.getParameter<double>("drVetoEndcap"),
533  .ecaletaStripBarrel = pfECALClusIsolCfg.getParameter<double>("etaStripBarrel"),
534  .ecaletaStripEndcap = pfECALClusIsolCfg.getParameter<double>("etaStripEndcap"),
535  .ecalenergyBarrel = pfECALClusIsolCfg.getParameter<double>("energyBarrel"),
536  .ecalenergyEndcap = pfECALClusIsolCfg.getParameter<double>("energyEndcap"),
537  .useHF = pfHCALClusIsolCfg.getParameter<bool>("useHF"),
538  .hcaldrMax = pfHCALClusIsolCfg.getParameter<double>("drMax"),
539  .hcaldrVetoBarrel = pfHCALClusIsolCfg.getParameter<double>("drVetoBarrel"),
540  .hcaldrVetoEndcap = pfHCALClusIsolCfg.getParameter<double>("drVetoEndcap"),
541  .hcaletaStripBarrel = pfHCALClusIsolCfg.getParameter<double>("etaStripBarrel"),
542  .hcaletaStripEndcap = pfHCALClusIsolCfg.getParameter<double>("etaStripEndcap"),
543  .hcalenergyBarrel = pfHCALClusIsolCfg.getParameter<double>("energyBarrel"),
544  .hcalenergyEndcap = pfHCALClusIsolCfg.getParameter<double>("energyEndcap"),
545  .hcaluseEt = pfHCALClusIsolCfg.getParameter<bool>("useEt")};
546 
547  const RegressionHelper::Configuration regressionCfg{
548  .ecalRegressionWeightLabels = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightLabels"),
549  .ecalWeightsFromDB = cfg.getParameter<bool>("ecalWeightsFromDB"),
550  .ecalRegressionWeightFiles = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightFiles"),
552  cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightLabels"),
553  .combinationWeightsFromDB = cfg.getParameter<bool>("combinationWeightsFromDB"),
554  .combinationRegressionWeightFiles =
555  cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightFile")};
556 
557  // create algo
558  algo_ = std::make_unique<GsfElectronAlgo>(
559  inputCfg_,
560  strategyCfg_,
561  cutsCfg_,
562  hcalCfg_,
563  hcalCfgBc_,
564  isoCfg,
565  pfisoCfg,
566  recHitsCfg,
568  cfg.getParameter<std::string>("crackCorrectionFunction"), cfg, consumesCollector()),
569  regressionCfg,
570  cfg.getParameter<edm::ParameterSet>("trkIsol03Cfg"),
571  cfg.getParameter<edm::ParameterSet>("trkIsol04Cfg"),
572  cfg.getParameter<edm::ParameterSet>("trkIsolHEEP03Cfg"),
573  cfg.getParameter<edm::ParameterSet>("trkIsolHEEP04Cfg"),
574  consumesCollector());
575 
576  if (dnnPFidEnabled_) {
577  tfSessions_ = gcache->iElectronDNNEstimator->getSessions();
578  }
579 }
580 
582  for (auto session : tfSessions_) {
583  tensorflow::closeSession(session);
584  }
585 }
586 
588  if (!pset.exists("SeedConfiguration")) {
589  return;
590  }
591  edm::ParameterSet seedConfiguration = pset.getParameter<edm::ParameterSet>("SeedConfiguration");
592 
593  if (seedConfiguration.getParameter<bool>("applyHOverECut")) {
594  if ((hcalCfg_.hOverEConeSize != 0) &&
595  (hcalCfg_.hOverEConeSize != seedConfiguration.getParameter<double>("hOverEConeSize"))) {
596  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
597  << "The H/E cone size (" << hcalCfg_.hOverEConeSize << ") is different from ecal seeding ("
598  << seedConfiguration.getParameter<double>("hOverEConeSize") << ").";
599  }
600  if (cutsCfg_.maxHOverEBarrelCone < seedConfiguration.getParameter<double>("maxHOverEBarrel")) {
601  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
602  << "The max barrel cone H/E is lower than during ecal seeding.";
603  }
604  if (cutsCfg_.maxHOverEEndcapsCone < seedConfiguration.getParameter<double>("maxHOverEEndcaps")) {
605  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
606  << "The max endcaps cone H/E is lower than during ecal seeding.";
607  }
608  }
609 
610  if (cutsCfg_.minSCEtBarrel < seedConfiguration.getParameter<double>("SCEtCut")) {
611  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
612  << "The minimum super-cluster Et in barrel is lower than during ecal seeding.";
613  }
614  if (cutsCfg_.minSCEtEndcaps < seedConfiguration.getParameter<double>("SCEtCut")) {
615  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
616  << "The minimum super-cluster Et in endcaps is lower than during ecal seeding.";
617  }
618 }
619 
620 //=======================================================================================
621 // Ambiguity solving
622 //=======================================================================================
623 
625  edm::Event const& event,
626  bool ignoreNotPreselected) const {
627  // Getting required event data
628  auto const& beamspot = event.get(inputCfg_.beamSpotTag);
629  auto gsfPfRecTracks =
631  auto const& barrelRecHits = event.get(inputCfg_.barrelRecHitCollection);
632  auto const& endcapRecHits = event.get(inputCfg_.endcapRecHitCollection);
633 
634  if (strategyCfg_.ambSortingStrategy == 0) {
636  } else if (strategyCfg_.ambSortingStrategy == 1) {
638  } else {
639  throw cms::Exception("GsfElectronAlgo|UnknownAmbiguitySortingStrategy")
640  << "value of strategyCfg_.ambSortingStrategy is : " << strategyCfg_.ambSortingStrategy;
641  }
642 
643  // init
644  for (auto& electron : electrons) {
645  electron.clearAmbiguousGsfTracks();
646  electron.setAmbiguous(false);
647  }
648 
649  // get ambiguous from GsfPfRecTracks
650  if (useGsfPfRecTracks_) {
651  for (auto& e1 : electrons) {
652  bool found = false;
653  for (auto const& gsfPfRecTrack : *gsfPfRecTracks) {
654  if (gsfPfRecTrack.gsfTrackRef() == e1.gsfTrack()) {
655  if (found) {
656  edm::LogWarning("GsfElectronAlgo") << "associated gsfPfRecTrack already found";
657  } else {
658  found = true;
659  for (auto const& duplicate : gsfPfRecTrack.convBremGsfPFRecTrackRef()) {
660  e1.addAmbiguousGsfTrack(duplicate->gsfTrackRef());
661  }
662  }
663  }
664  }
665  }
666  }
667  // or search overlapping clusters
668  else {
669  for (auto e1 = electrons.begin(); e1 != electrons.end(); ++e1) {
670  if (e1->ambiguous())
671  continue;
673  continue;
674 
675  SuperClusterRef scRef1 = e1->superCluster();
676  CaloClusterPtr eleClu1 = e1->electronCluster();
677  LogDebug("GsfElectronAlgo") << "Blessing electron with E/P " << e1->eSuperClusterOverP() << ", cluster "
678  << scRef1.get() << " & track " << e1->gsfTrack().get();
679 
680  for (auto e2 = e1 + 1; e2 != electrons.end(); ++e2) {
681  if (e2->ambiguous())
682  continue;
683  if (ignoreNotPreselected && !isPreselected(*e2))
684  continue;
685 
686  SuperClusterRef scRef2 = e2->superCluster();
687  CaloClusterPtr eleClu2 = e2->electronCluster();
688 
689  // search if same cluster
690  bool sameCluster = false;
692  sameCluster = (scRef1 == scRef2);
693  } else if (strategyCfg_.ambClustersOverlapStrategy == 1) {
694  float eMin = 1.;
695  float threshold = eMin * cosh(EleRelPoint(scRef1->position(), beamspot.position()).eta());
696  using egamma::sharedEnergy;
697  sameCluster = ((sharedEnergy(*eleClu1, *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
698  (sharedEnergy(*scRef1->seed(), *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
699  (sharedEnergy(*eleClu1, *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold) ||
700  (sharedEnergy(*scRef1->seed(), *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold));
701  } else {
702  throw cms::Exception("GsfElectronAlgo|UnknownAmbiguityClustersOverlapStrategy")
703  << "value of strategyCfg_.ambClustersOverlapStrategy is : " << strategyCfg_.ambClustersOverlapStrategy;
704  }
705 
706  // main instructions
707  if (sameCluster) {
708  LogDebug("GsfElectronAlgo") << "Discarding electron with E/P " << e2->eSuperClusterOverP() << ", cluster "
709  << scRef2.get() << " and track " << e2->gsfTrack().get();
710  e1->addAmbiguousGsfTrack(e2->gsfTrack());
711  e2->setAmbiguous(true);
712  } else if (e1->gsfTrack() == e2->gsfTrack()) {
713  edm::LogWarning("GsfElectronAlgo") << "Forgetting electron with E/P " << e2->eSuperClusterOverP()
714  << ", cluster " << scRef2.get() << " and track " << e2->gsfTrack().get();
715  e2->setAmbiguous(true);
716  }
717  }
718  }
719  }
720 }
721 
723  bool passCutBased = ele.passingCutBasedPreselection();
724  bool passPF = ele.passingPflowPreselection();
725  // it is worth nothing for gedGsfElectrons, this does nothing as its not set
726  // till GedGsfElectron finaliser, this is always false
727  bool passmva = ele.passingMvaPreselection();
728  if (!ele.ecalDrivenSeed()) {
729  if (ele.pt() > strategyCfg_.MaxElePtForOnlyMVA)
730  return passmva && passCutBased;
731  else
732  return passmva;
733  } else {
734  return passCutBased || passPF || passmva;
735  }
736 }
737 
738 // ------------ method called to produce the data ------------
740  HcalPFCuts const* hcalCuts = nullptr;
741  if (cutsFromDB_) {
742  hcalCuts = &setup.getData(hcalCutsToken_);
743  }
744 
745  // check configuration
748  auto seeds = event.getHandle(inputCfg_.seedsTag);
749  if (!seeds.isValid()) {
750  edm::LogWarning("GsfElectronAlgo|UnreachableSeedsProvenance")
751  << "Cannot check consistency of parameters with ecal seeding ones,"
752  << " because the original collection of seeds is not any more available.";
753  } else {
754  checkEcalSeedingParameters(edm::parameterSet(seeds.provenance()->stable(), event.processHistory()));
755  }
756  }
757 
758  auto electrons = algo_->completeElectrons(event, setup, globalCache(), hcalCuts);
760  const auto gsfMVAInputMap = matchWithPFCandidates(event.get(egmPFCandidateCollection_));
761  for (auto& el : electrons) {
762  el.setMvaInput(gsfMVAInputMap.find(el.gsfTrack())->second); // set Run2 MVA inputs
763  }
764  setMVAOutputs(
766  }
767 
768  // all electrons
769  logElectrons(electrons, event, "GsfElectronAlgo Info (before preselection)");
770  // preselection
772  electrons.erase(
773  std::remove_if(electrons.begin(), electrons.end(), [this](auto const& ele) { return !isPreselected(ele); }),
774  electrons.end());
775  logElectrons(electrons, event, "GsfElectronAlgo Info (after preselection)");
776  }
777  // ambiguity
780  electrons.erase(std::remove_if(electrons.begin(), electrons.end(), std::mem_fn(&reco::GsfElectron::ambiguous)),
781  electrons.end());
782  logElectrons(electrons, event, "GsfElectronAlgo Info (after amb. solving)");
783  }
784  // 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
785  if (hcalRun2EffDepth_) {
786  for (auto& ele : electrons)
787  ele.hcalToRun2EffDepth();
788  }
789  // final filling
790  event.emplace(electronPutToken_, std::move(electrons));
791 }
792 
void checkEcalSeedingParameters(edm::ParameterSet const &)
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
const edm::EDGetTokenT< reco::GsfPFRecTrackCollection > gsfPfRecTracksTag_
GsfElectronAlgo::Tokens inputCfg_
double pt() const final
transverse momentum
bool ecalDrivenSeed() const
Definition: GsfElectron.h:158
edm::EDGetTokenT< reco::PFCandidateCollection > egmPFCandidateCollection_
std::vector< std::string > ecalRegressionWeightLabels
static void fillDescriptions(edm::ConfigurationDescriptions &)
const bool resetMvaValuesUsingPFCandidates_
bool passingPflowPreselection() const
Definition: GsfElectron.h:764
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
bool ambiguous() const
Definition: GsfElectron.h:765
edm::EDGetTokenT< reco::VertexCollection > vtxCollectionTag
edm::EDGetTokenT< EcalRecHitCollection > endcapRecHitCollection
assert(be >=bs)
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
std::vector< GsfElectron > GsfElectronCollection
collection of GsfElectron objects
edm::ESGetToken< HcalPFCuts, HcalPFCutsRcd > hcalCutsToken_
ElectronHcalHelper::Configuration hcalCfg_
#define LogTrace(id)
static std::string const input
Definition: EdmProvDump.cc:50
std::unique_ptr< const ElectronMVAEstimator > iElectronMVAEstimator
U second(std::pair< T, U > const &p)
bool isBetterElectron(reco::GsfElectron const &, reco::GsfElectron const &)
bool isInnermostElectron(reco::GsfElectron const &, reco::GsfElectron const &)
GsfElectronProducer(const edm::ParameterSet &, const GsfElectronAlgo::HeavyObjectCache *)
static std::unique_ptr< GsfElectronAlgo::HeavyObjectCache > initializeGlobalCache(const edm::ParameterSet &conf)
const edm::EDPutTokenT< reco::GsfElectronCollection > electronPutToken_
edm::EDGetTokenT< reco::BeamSpot > beamSpotTag
bool closeSession(Session *&session)
Definition: TensorFlow.cc:234
std::vector< tensorflow::Session * > tfSessions_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static edm::ParameterSetDescription pSetDescript()
edm::EDGetTokenT< reco::ElectronSeedCollection > seedsTag
std::unique_ptr< const ElectronDNNEstimator > iElectronDNNEstimator
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool isPreselected(reco::GsfElectron const &ele) const
void setAmbiguityData(reco::GsfElectronCollection &electrons, edm::Event const &event, bool ignoreNotPreselected=true) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const GsfElectronAlgo::CutsConfiguration cutsCfg_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
float sharedEnergy(reco::CaloCluster const &clu1, reco::CaloCluster const &clu2, EcalRecHitCollection const &barrelRecHits, EcalRecHitCollection const &endcapRecHits)
bool passingMvaPreselection() const
Definition: GsfElectron.h:778
fixed size matrix
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
edm::EDGetTokenT< EcalRecHitCollection > barrelRecHitCollection
std::unique_ptr< GsfElectronAlgo > algo_
ElectronHcalHelper::Configuration hcalCfgBc_
std::unique_ptr< const SoftElectronMVAEstimator > sElectronMVAEstimator
#define get
Log< level::Warning, false > LogWarning
std::array< double, 4 > arrayHB
static void globalEndJob(GsfElectronAlgo::HeavyObjectCache const *)
void produce(edm::Event &event, const edm::EventSetup &setup) override
def move(src, dest)
Definition: eostools.py:511
bool passingCutBasedPreselection() const
Definition: GsfElectron.h:763
GsfElectronAlgo::StrategyConfiguration strategyCfg_
Definition: event.py:1
#define LogDebug(id)
std::array< double, 7 > arrayHE