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 };
170 
173  // input collections
174  desc.add<edm::InputTag>("gsfElectronCoresTag", {"ecalDrivenGsfElectronCores"});
175  desc.add<edm::InputTag>("vtxTag", {"offlinePrimaryVertices"});
176  desc.add<edm::InputTag>("conversionsTag", {"allConversions"});
177  desc.add<edm::InputTag>("gsfPfRecTracksTag", {"pfTrackElec"});
178  desc.add<edm::InputTag>("barrelRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEB"});
179  desc.add<edm::InputTag>("endcapRecHitCollectionTag", {"ecalRecHit", "EcalRecHitsEE"});
180  desc.add<edm::InputTag>("seedsTag", {"ecalDrivenElectronSeeds"});
181  desc.add<edm::InputTag>("beamSpotTag", {"offlineBeamSpot"});
182  desc.add<edm::InputTag>("egmPFCandidatesTag", {"particleFlowEGamma"});
183 
184  // steering
185  desc.add<bool>("useDefaultEnergyCorrection", true);
186  desc.add<bool>("useCombinationRegression", false);
187  desc.add<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization", true);
188  desc.add<bool>("ecalDrivenEcalErrorFromClassBasedParameterization", true);
189  desc.add<bool>("applyPreselection", false);
190  desc.add<bool>("useEcalRegression", false);
191  desc.add<bool>("applyAmbResolution", false);
192  desc.add<bool>("ignoreNotPreselected", true);
193  desc.add<bool>("useGsfPfRecTracks", true);
194  desc.add<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization", true);
195  desc.add<unsigned int>("ambSortingStrategy", 1);
196  desc.add<unsigned int>("ambClustersOverlapStrategy", 1);
197  desc.add<bool>("fillConvVtxFitProb", true);
198  desc.add<bool>("resetMvaValuesUsingPFCandidates", false);
199 
200  // Ecal rec hits configuration
201  desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
202  desc.add<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
203  desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
204  desc.add<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
205 
206  // Hcal rec hits configuration
207  desc.add<bool>("checkHcalStatus", true);
208  desc.add<edm::InputTag>("hbheRecHits", edm::InputTag("hbhereco"));
209  desc.add<std::vector<double>>("recHitEThresholdHB", {0., 0., 0., 0.});
210  desc.add<std::vector<double>>("recHitEThresholdHE", {0., 0., 0., 0., 0., 0., 0.});
211  desc.add<int>("maxHcalRecHitSeverity", 999999);
212  desc.add<bool>("hcalRun2EffDepth", false);
213 
214  // Isolation algos configuration
215  desc.add("trkIsol03Cfg", EleTkIsolFromCands::pSetDescript());
216  desc.add("trkIsol04Cfg", EleTkIsolFromCands::pSetDescript());
217  desc.add("trkIsolHEEP03Cfg", EleTkIsolFromCands::pSetDescript());
218  desc.add("trkIsolHEEP04Cfg", EleTkIsolFromCands::pSetDescript());
219  desc.add<bool>("useNumCrystals", true);
220  desc.add<double>("etMinBarrel", 0.0);
221  desc.add<double>("etMinEndcaps", 0.11);
222  desc.add<double>("etMinHcal", 0.0);
223  desc.add<double>("eMinBarrel", 0.095);
224  desc.add<double>("eMinEndcaps", 0.0);
225  desc.add<double>("intRadiusEcalBarrel", 3.0);
226  desc.add<double>("intRadiusEcalEndcaps", 3.0);
227  desc.add<double>("intRadiusHcal", 0.15);
228  desc.add<double>("jurassicWidth", 1.5);
229  desc.add<bool>("vetoClustered", false);
230 
231  // backward compatibility mechanism for ctf tracks
232  desc.add<bool>("ctfTracksCheck", true);
233  desc.add<edm::InputTag>("ctfTracksTag", {"generalTracks"});
234 
235  desc.add<double>("MaxElePtForOnlyMVA", 50.0);
236  desc.add<double>("PreSelectMVA", -0.1);
237 
238  {
240  psd0.add<double>("minSCEtBarrel", 4.0);
241  psd0.add<double>("minSCEtEndcaps", 4.0);
242  psd0.add<double>("minEOverPBarrel", 0.0);
243  psd0.add<double>("minEOverPEndcaps", 0.0);
244  psd0.add<double>("maxEOverPBarrel", 999999999.0);
245  psd0.add<double>("maxEOverPEndcaps", 999999999.0);
246  psd0.add<double>("maxDeltaEtaBarrel", 0.02);
247  psd0.add<double>("maxDeltaEtaEndcaps", 0.02);
248  psd0.add<double>("maxDeltaPhiBarrel", 0.15);
249  psd0.add<double>("maxDeltaPhiEndcaps", 0.15);
250  psd0.add<double>("hOverEConeSize", 0.15);
251  psd0.add<double>("maxHOverEBarrelCone", 0.15);
252  psd0.add<double>("maxHOverEEndcapsCone", 0.15);
253  psd0.add<double>("maxHBarrelCone", 0.0);
254  psd0.add<double>("maxHEndcapsCone", 0.0);
255  psd0.add<double>("maxHOverEBarrelBc", 0.15);
256  psd0.add<double>("maxHOverEEndcapsBc", 0.15);
257  psd0.add<double>("maxHBarrelBc", 0.0);
258  psd0.add<double>("maxHEndcapsBc", 0.0);
259  psd0.add<double>("maxSigmaIetaIetaBarrel", 999999999.0);
260  psd0.add<double>("maxSigmaIetaIetaEndcaps", 999999999.0);
261  psd0.add<double>("maxFbremBarrel", 999999999.0);
262  psd0.add<double>("maxFbremEndcaps", 999999999.0);
263  psd0.add<bool>("isBarrel", false);
264  psd0.add<bool>("isEndcaps", false);
265  psd0.add<bool>("isFiducial", false);
266  psd0.add<bool>("seedFromTEC", true);
267  psd0.add<double>("maxTIP", 999999999.0);
268  psd0.add<double>("multThresEB", EgammaLocalCovParamDefaults::kMultThresEB);
269  psd0.add<double>("multThresEE", EgammaLocalCovParamDefaults::kMultThresEE);
270  // preselection parameters
271  desc.add<edm::ParameterSetDescription>("preselection", psd0);
272  }
273 
274  // Corrections
275  desc.add<std::string>("crackCorrectionFunction", "EcalClusterCrackCorrection");
276 
277  desc.add<bool>("ecalWeightsFromDB", true);
278  desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightFiles", {})
279  ->setComment("if not from DB. Otherwise, keep empty");
280  desc.add<bool>("combinationWeightsFromDB", true);
281  desc.add<std::vector<std::string>>("combinationRegressionWeightFile", {})
282  ->setComment("if not from DB. Otherwise, keep empty");
283 
284  // regression. The labels are needed in all cases.
285  desc.add<std::vector<std::string>>("ecalRefinedRegressionWeightLabels", {});
286  desc.add<std::vector<std::string>>("combinationRegressionWeightLabels", {});
287 
288  desc.add<std::vector<std::string>>(
289  "ElecMVAFilesString",
290  {
291  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_10_17Feb2011.weights.xml",
292  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_12_17Feb2011.weights.xml",
293  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_20_17Feb2011.weights.xml",
294  "RecoEgamma/ElectronIdentification/data/TMVA_Category_BDTSimpleCat_22_17Feb2011.weights.xml",
295  });
296  desc.add<std::vector<std::string>>(
297  "SoftElecMVAFilesString",
298  {
299  "RecoEgamma/ElectronIdentification/data/TMVA_BDTSoftElectrons_7Feb2014.weights.xml",
300  });
301 
302  {
304  psd1.add<bool>("enabled", false);
305  psd1.add<double>("extetaboundary", 2.65);
306  psd1.add<std::string>("inputTensorName", "FirstLayer_input");
307  psd1.add<std::string>("outputTensorName", "sequential/FinalLayer/Softmax");
308 
309  psd1.add<std::vector<std::string>>(
310  "modelsFiles",
311  {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_modelDNN.pb",
312  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_modelDNN.pb",
313  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_modelDNN.pb",
314  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/modelDNN.pb",
315  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/modelDNN.pb"});
316  psd1.add<std::vector<std::string>>(
317  "scalersFiles",
318  {"RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/lowpT/lowpT_scaler.txt",
319  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEB/highpTEB_scaler.txt",
320  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Summer21_120X/highpTEE/highpTEE_scaler.txt",
321  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta1/scaler.txt",
322  "RecoEgamma/ElectronIdentification/data/Ele_PFID_dnn/Run3Winter22_122X/exteta2/scaler.txt"});
323  psd1.add<std::vector<unsigned int>>("outputDim", //Number of output nodes for the above models
324  {5, 5, 5, 5, 3});
325 
326  psd1.add<bool>("useEBModelInGap", true);
327  // preselection parameters
328  desc.add<edm::ParameterSetDescription>("EleDNNPFid", psd1);
329  }
330 
333  {
335  psd0.add<edm::InputTag>("pfClusterProducer", edm::InputTag("particleFlowClusterECAL"));
336  psd0.add<double>("drMax", 0.3);
337  psd0.add<double>("drVetoBarrel", 0.0);
338  psd0.add<double>("drVetoEndcap", 0.0);
339  psd0.add<double>("etaStripBarrel", 0.0);
340  psd0.add<double>("etaStripEndcap", 0.0);
341  psd0.add<double>("energyBarrel", 0.0);
342  psd0.add<double>("energyEndcap", 0.0);
343  desc.add<edm::ParameterSetDescription>("pfECALClusIsolCfg", psd0);
344  }
345 
347  {
349  psd0.add<edm::InputTag>("pfClusterProducerHCAL", edm::InputTag("particleFlowClusterHCAL"));
350  psd0.add<edm::InputTag>("pfClusterProducerHFEM", edm::InputTag(""));
351  psd0.add<edm::InputTag>("pfClusterProducerHFHAD", edm::InputTag(""));
352  psd0.add<bool>("useHF", false);
353  psd0.add<double>("drMax", 0.3);
354  psd0.add<double>("drVetoBarrel", 0.0);
355  psd0.add<double>("drVetoEndcap", 0.0);
356  psd0.add<double>("etaStripBarrel", 0.0);
357  psd0.add<double>("etaStripEndcap", 0.0);
358  psd0.add<double>("energyBarrel", 0.0);
359  psd0.add<double>("energyEndcap", 0.0);
360  psd0.add<bool>("useEt", true);
361  desc.add<edm::ParameterSetDescription>("pfHCALClusIsolCfg", psd0);
362  }
363 
364  descriptions.add("gsfElectronProducerDefault", desc);
365 }
366 
367 namespace {
368  GsfElectronAlgo::CutsConfiguration makeCutsConfiguration(edm::ParameterSet const& pset) {
370  .minSCEtBarrel = pset.getParameter<double>("minSCEtBarrel"),
371  .minSCEtEndcaps = pset.getParameter<double>("minSCEtEndcaps"),
372  .maxEOverPBarrel = pset.getParameter<double>("maxEOverPBarrel"),
373  .maxEOverPEndcaps = pset.getParameter<double>("maxEOverPEndcaps"),
374  .minEOverPBarrel = pset.getParameter<double>("minEOverPBarrel"),
375  .minEOverPEndcaps = pset.getParameter<double>("minEOverPEndcaps"),
376  .maxHOverEBarrelCone = pset.getParameter<double>("maxHOverEBarrelCone"),
377  .maxHOverEEndcapsCone = pset.getParameter<double>("maxHOverEEndcapsCone"),
378  .maxHBarrelCone = pset.getParameter<double>("maxHBarrelCone"),
379  .maxHEndcapsCone = pset.getParameter<double>("maxHEndcapsCone"),
380  .maxHOverEBarrelBc = pset.getParameter<double>("maxHOverEBarrelBc"),
381  .maxHOverEEndcapsBc = pset.getParameter<double>("maxHOverEEndcapsBc"),
382  .maxHBarrelBc = pset.getParameter<double>("maxHBarrelBc"),
383  .maxHEndcapsBc = pset.getParameter<double>("maxHEndcapsBc"),
384  .maxDeltaEtaBarrel = pset.getParameter<double>("maxDeltaEtaBarrel"),
385  .maxDeltaEtaEndcaps = pset.getParameter<double>("maxDeltaEtaEndcaps"),
386  .maxDeltaPhiBarrel = pset.getParameter<double>("maxDeltaPhiBarrel"),
387  .maxDeltaPhiEndcaps = pset.getParameter<double>("maxDeltaPhiEndcaps"),
388  .maxSigmaIetaIetaBarrel = pset.getParameter<double>("maxSigmaIetaIetaBarrel"),
389  .maxSigmaIetaIetaEndcaps = pset.getParameter<double>("maxSigmaIetaIetaEndcaps"),
390  .maxFbremBarrel = pset.getParameter<double>("maxFbremBarrel"),
391  .maxFbremEndcaps = pset.getParameter<double>("maxFbremEndcaps"),
392  .isBarrel = pset.getParameter<bool>("isBarrel"),
393  .isEndcaps = pset.getParameter<bool>("isEndcaps"),
394  .isFiducial = pset.getParameter<bool>("isFiducial"),
395  .maxTIP = pset.getParameter<double>("maxTIP"),
396  .seedFromTEC = pset.getParameter<bool>("seedFromTEC"),
397  .multThresEB = pset.getParameter<double>("multThresEB"),
398  .multThresEE = pset.getParameter<double>("multThresEE"),
399  };
400  }
401 }; // namespace
402 
404  : cutsCfg_{makeCutsConfiguration(cfg.getParameter<edm::ParameterSet>("preselection"))},
405  ecalSeedingParametersChecked_(false),
406  electronPutToken_(produces<GsfElectronCollection>()),
407  gsfPfRecTracksTag_(consumes(cfg.getParameter<edm::InputTag>("gsfPfRecTracksTag"))),
408  useGsfPfRecTracks_(cfg.getParameter<bool>("useGsfPfRecTracks")),
409  resetMvaValuesUsingPFCandidates_(cfg.getParameter<bool>("resetMvaValuesUsingPFCandidates")) {
410  if (resetMvaValuesUsingPFCandidates_) {
411  egmPFCandidateCollection_ = consumes(cfg.getParameter<edm::InputTag>("egmPFCandidatesTag"));
412  }
413 
414  inputCfg_.gsfElectronCores = consumes(cfg.getParameter<edm::InputTag>("gsfElectronCoresTag"));
415  inputCfg_.hbheRecHitsTag = consumes(cfg.getParameter<edm::InputTag>("hbheRecHits"));
416  inputCfg_.barrelRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("barrelRecHitCollectionTag"));
417  inputCfg_.endcapRecHitCollection = consumes(cfg.getParameter<edm::InputTag>("endcapRecHitCollectionTag"));
418  inputCfg_.ctfTracks = consumes(cfg.getParameter<edm::InputTag>("ctfTracksTag"));
419  // used to check config consistency with seeding
420  inputCfg_.seedsTag = consumes(cfg.getParameter<edm::InputTag>("seedsTag"));
421  inputCfg_.beamSpotTag = consumes(cfg.getParameter<edm::InputTag>("beamSpotTag"));
422  inputCfg_.vtxCollectionTag = consumes(cfg.getParameter<edm::InputTag>("vtxTag"));
423  if (cfg.getParameter<bool>("fillConvVtxFitProb"))
424  inputCfg_.conversions = consumes(cfg.getParameter<edm::InputTag>("conversionsTag"));
425 
426  // inputs for PFCluster isolation
427  const edm::ParameterSet& pfECALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfECALClusIsolCfg");
428  const edm::ParameterSet& pfHCALClusIsolCfg = cfg.getParameter<edm::ParameterSet>("pfHCALClusIsolCfg");
429  inputCfg_.pfClusterProducer =
430  consumes<reco::PFClusterCollection>(pfECALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducer"));
431  inputCfg_.pfClusterProducerHCAL = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHCAL"));
432  inputCfg_.pfClusterProducerHFEM = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFEM"));
433  inputCfg_.pfClusterProducerHFHAD = consumes(pfHCALClusIsolCfg.getParameter<edm::InputTag>("pfClusterProducerHFHAD"));
434 
435  // Config for PFID dnn
436  const auto& pset_dnn = cfg.getParameter<edm::ParameterSet>("EleDNNPFid");
437  dnnPFidEnabled_ = pset_dnn.getParameter<bool>("enabled");
438  extetaboundary_ = pset_dnn.getParameter<double>("extetaboundary");
439 
440  strategyCfg_.useDefaultEnergyCorrection = cfg.getParameter<bool>("useDefaultEnergyCorrection");
441 
442  strategyCfg_.applyPreselection = cfg.getParameter<bool>("applyPreselection");
443  strategyCfg_.ecalDrivenEcalEnergyFromClassBasedParameterization =
444  cfg.getParameter<bool>("ecalDrivenEcalEnergyFromClassBasedParameterization");
445  strategyCfg_.ecalDrivenEcalErrorFromClassBasedParameterization =
446  cfg.getParameter<bool>("ecalDrivenEcalErrorFromClassBasedParameterization");
447  strategyCfg_.pureTrackerDrivenEcalErrorFromSimpleParameterization =
448  cfg.getParameter<bool>("pureTrackerDrivenEcalErrorFromSimpleParameterization");
449  strategyCfg_.applyAmbResolution = cfg.getParameter<bool>("applyAmbResolution");
450  strategyCfg_.ignoreNotPreselected = cfg.getParameter<bool>("ignoreNotPreselected");
451  strategyCfg_.ambSortingStrategy = cfg.getParameter<unsigned>("ambSortingStrategy");
452  strategyCfg_.ambClustersOverlapStrategy = cfg.getParameter<unsigned>("ambClustersOverlapStrategy");
453  strategyCfg_.ctfTracksCheck = cfg.getParameter<bool>("ctfTracksCheck");
454  strategyCfg_.PreSelectMVA = cfg.getParameter<double>("PreSelectMVA");
455  strategyCfg_.MaxElePtForOnlyMVA = cfg.getParameter<double>("MaxElePtForOnlyMVA");
456  strategyCfg_.useEcalRegression = cfg.getParameter<bool>("useEcalRegression");
457  strategyCfg_.useCombinationRegression = cfg.getParameter<bool>("useCombinationRegression");
458  strategyCfg_.fillConvVtxFitProb = cfg.getParameter<bool>("fillConvVtxFitProb");
459  strategyCfg_.computePfClusterIso = dnnPFidEnabled_;
460 
461  // hcal helpers
462  auto const& psetPreselection = cfg.getParameter<edm::ParameterSet>("preselection");
463  hcalCfg_.hOverEConeSize = psetPreselection.getParameter<double>("hOverEConeSize");
464  if (hcalCfg_.hOverEConeSize > 0) {
465  hcalCfg_.onlyBehindCluster = false;
466  hcalCfg_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
467 
468  //hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
469  hcalCfg_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
470 
471  hcalCfg_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
472  hcalCfg_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
473  hcalCfg_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
474  hcalCfg_.maxSeverityHE = hcalCfg_.maxSeverityHB;
475  }
476 
477  hcalCfgBc_.hOverEConeSize = 0.;
478  hcalCfgBc_.onlyBehindCluster = true;
479  hcalCfgBc_.checkHcalStatus = cfg.getParameter<bool>("checkHcalStatus");
480 
481  //hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
482  hcalCfgBc_.hbheRecHits = consumes<HBHERecHitCollection>(cfg.getParameter<edm::InputTag>("hbheRecHits"));
483 
484  hcalCfgBc_.eThresHB = cfg.getParameter<EgammaHcalIsolation::arrayHB>("recHitEThresholdHB");
485  hcalCfgBc_.maxSeverityHB = cfg.getParameter<int>("maxHcalRecHitSeverity");
486  hcalCfgBc_.eThresHE = cfg.getParameter<EgammaHcalIsolation::arrayHE>("recHitEThresholdHE");
487  hcalCfgBc_.maxSeverityHE = hcalCfgBc_.maxSeverityHB;
488 
489  hcalRun2EffDepth_ = cfg.getParameter<bool>("hcalRun2EffDepth");
490 
491  // Ecal rec hits configuration
493  auto const& flagnamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedBarrel");
494  recHitsCfg.recHitFlagsToBeExcludedBarrel = StringToEnumValue<EcalRecHit::Flags>(flagnamesbarrel);
495  auto const& flagnamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitFlagsToBeExcludedEndcaps");
496  recHitsCfg.recHitFlagsToBeExcludedEndcaps = StringToEnumValue<EcalRecHit::Flags>(flagnamesendcaps);
497  auto const& severitynamesbarrel = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedBarrel");
498  recHitsCfg.recHitSeverityToBeExcludedBarrel =
499  StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesbarrel);
500  auto const& severitynamesendcaps = cfg.getParameter<std::vector<std::string>>("recHitSeverityToBeExcludedEndcaps");
501  recHitsCfg.recHitSeverityToBeExcludedEndcaps =
502  StringToEnumValue<EcalSeverityLevel::SeverityLevel>(severitynamesendcaps);
503 
504  // isolation
506  .intRadiusHcal = cfg.getParameter<double>("intRadiusHcal"),
507  .etMinHcal = cfg.getParameter<double>("etMinHcal"),
508  .intRadiusEcalBarrel = cfg.getParameter<double>("intRadiusEcalBarrel"),
509  .intRadiusEcalEndcaps = cfg.getParameter<double>("intRadiusEcalEndcaps"),
510  .jurassicWidth = cfg.getParameter<double>("jurassicWidth"),
511  .etMinBarrel = cfg.getParameter<double>("etMinBarrel"),
512  .eMinBarrel = cfg.getParameter<double>("eMinBarrel"),
513  .etMinEndcaps = cfg.getParameter<double>("etMinEndcaps"),
514  .eMinEndcaps = cfg.getParameter<double>("eMinEndcaps"),
515  .vetoClustered = cfg.getParameter<bool>("vetoClustered"),
516  .useNumCrystals = cfg.getParameter<bool>("useNumCrystals")};
517 
518  // isolation
520  .ecaldrMax = pfECALClusIsolCfg.getParameter<double>("drMax"),
521  .ecaldrVetoBarrel = pfECALClusIsolCfg.getParameter<double>("drVetoBarrel"),
522  .ecaldrVetoEndcap = pfECALClusIsolCfg.getParameter<double>("drVetoEndcap"),
523  .ecaletaStripBarrel = pfECALClusIsolCfg.getParameter<double>("etaStripBarrel"),
524  .ecaletaStripEndcap = pfECALClusIsolCfg.getParameter<double>("etaStripEndcap"),
525  .ecalenergyBarrel = pfECALClusIsolCfg.getParameter<double>("energyBarrel"),
526  .ecalenergyEndcap = pfECALClusIsolCfg.getParameter<double>("energyEndcap"),
527  .useHF = pfHCALClusIsolCfg.getParameter<bool>("useHF"),
528  .hcaldrMax = pfHCALClusIsolCfg.getParameter<double>("drMax"),
529  .hcaldrVetoBarrel = pfHCALClusIsolCfg.getParameter<double>("drVetoBarrel"),
530  .hcaldrVetoEndcap = pfHCALClusIsolCfg.getParameter<double>("drVetoEndcap"),
531  .hcaletaStripBarrel = pfHCALClusIsolCfg.getParameter<double>("etaStripBarrel"),
532  .hcaletaStripEndcap = pfHCALClusIsolCfg.getParameter<double>("etaStripEndcap"),
533  .hcalenergyBarrel = pfHCALClusIsolCfg.getParameter<double>("energyBarrel"),
534  .hcalenergyEndcap = pfHCALClusIsolCfg.getParameter<double>("energyEndcap"),
535  .hcaluseEt = pfHCALClusIsolCfg.getParameter<bool>("useEt")};
536 
537  const RegressionHelper::Configuration regressionCfg{
538  .ecalRegressionWeightLabels = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightLabels"),
539  .ecalWeightsFromDB = cfg.getParameter<bool>("ecalWeightsFromDB"),
540  .ecalRegressionWeightFiles = cfg.getParameter<std::vector<std::string>>("ecalRefinedRegressionWeightFiles"),
542  cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightLabels"),
543  .combinationWeightsFromDB = cfg.getParameter<bool>("combinationWeightsFromDB"),
544  .combinationRegressionWeightFiles =
545  cfg.getParameter<std::vector<std::string>>("combinationRegressionWeightFile")};
546 
547  // create algo
548  algo_ = std::make_unique<GsfElectronAlgo>(
549  inputCfg_,
550  strategyCfg_,
551  cutsCfg_,
552  hcalCfg_,
553  hcalCfgBc_,
554  isoCfg,
555  pfisoCfg,
556  recHitsCfg,
558  cfg.getParameter<std::string>("crackCorrectionFunction"), cfg, consumesCollector()),
559  regressionCfg,
560  cfg.getParameter<edm::ParameterSet>("trkIsol03Cfg"),
561  cfg.getParameter<edm::ParameterSet>("trkIsol04Cfg"),
562  cfg.getParameter<edm::ParameterSet>("trkIsolHEEP03Cfg"),
563  cfg.getParameter<edm::ParameterSet>("trkIsolHEEP04Cfg"),
564  consumesCollector());
565 
566  if (dnnPFidEnabled_) {
567  tfSessions_ = gcache->iElectronDNNEstimator->getSessions();
568  }
569 }
570 
572  for (auto session : tfSessions_) {
573  tensorflow::closeSession(session);
574  }
575 }
576 
578  if (!pset.exists("SeedConfiguration")) {
579  return;
580  }
581  edm::ParameterSet seedConfiguration = pset.getParameter<edm::ParameterSet>("SeedConfiguration");
582 
583  if (seedConfiguration.getParameter<bool>("applyHOverECut")) {
584  if ((hcalCfg_.hOverEConeSize != 0) &&
585  (hcalCfg_.hOverEConeSize != seedConfiguration.getParameter<double>("hOverEConeSize"))) {
586  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
587  << "The H/E cone size (" << hcalCfg_.hOverEConeSize << ") is different from ecal seeding ("
588  << seedConfiguration.getParameter<double>("hOverEConeSize") << ").";
589  }
590  if (cutsCfg_.maxHOverEBarrelCone < seedConfiguration.getParameter<double>("maxHOverEBarrel")) {
591  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
592  << "The max barrel cone H/E is lower than during ecal seeding.";
593  }
594  if (cutsCfg_.maxHOverEEndcapsCone < seedConfiguration.getParameter<double>("maxHOverEEndcaps")) {
595  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
596  << "The max endcaps cone H/E is lower than during ecal seeding.";
597  }
598  }
599 
600  if (cutsCfg_.minSCEtBarrel < seedConfiguration.getParameter<double>("SCEtCut")) {
601  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
602  << "The minimum super-cluster Et in barrel is lower than during ecal seeding.";
603  }
604  if (cutsCfg_.minSCEtEndcaps < seedConfiguration.getParameter<double>("SCEtCut")) {
605  edm::LogWarning("GsfElectronAlgo|InconsistentParameters")
606  << "The minimum super-cluster Et in endcaps is lower than during ecal seeding.";
607  }
608 }
609 
610 //=======================================================================================
611 // Ambiguity solving
612 //=======================================================================================
613 
615  edm::Event const& event,
616  bool ignoreNotPreselected) const {
617  // Getting required event data
618  auto const& beamspot = event.get(inputCfg_.beamSpotTag);
619  auto gsfPfRecTracks =
621  auto const& barrelRecHits = event.get(inputCfg_.barrelRecHitCollection);
622  auto const& endcapRecHits = event.get(inputCfg_.endcapRecHitCollection);
623 
624  if (strategyCfg_.ambSortingStrategy == 0) {
626  } else if (strategyCfg_.ambSortingStrategy == 1) {
628  } else {
629  throw cms::Exception("GsfElectronAlgo|UnknownAmbiguitySortingStrategy")
630  << "value of strategyCfg_.ambSortingStrategy is : " << strategyCfg_.ambSortingStrategy;
631  }
632 
633  // init
634  for (auto& electron : electrons) {
635  electron.clearAmbiguousGsfTracks();
636  electron.setAmbiguous(false);
637  }
638 
639  // get ambiguous from GsfPfRecTracks
640  if (useGsfPfRecTracks_) {
641  for (auto& e1 : electrons) {
642  bool found = false;
643  for (auto const& gsfPfRecTrack : *gsfPfRecTracks) {
644  if (gsfPfRecTrack.gsfTrackRef() == e1.gsfTrack()) {
645  if (found) {
646  edm::LogWarning("GsfElectronAlgo") << "associated gsfPfRecTrack already found";
647  } else {
648  found = true;
649  for (auto const& duplicate : gsfPfRecTrack.convBremGsfPFRecTrackRef()) {
650  e1.addAmbiguousGsfTrack(duplicate->gsfTrackRef());
651  }
652  }
653  }
654  }
655  }
656  }
657  // or search overlapping clusters
658  else {
659  for (auto e1 = electrons.begin(); e1 != electrons.end(); ++e1) {
660  if (e1->ambiguous())
661  continue;
663  continue;
664 
665  SuperClusterRef scRef1 = e1->superCluster();
666  CaloClusterPtr eleClu1 = e1->electronCluster();
667  LogDebug("GsfElectronAlgo") << "Blessing electron with E/P " << e1->eSuperClusterOverP() << ", cluster "
668  << scRef1.get() << " & track " << e1->gsfTrack().get();
669 
670  for (auto e2 = e1 + 1; e2 != electrons.end(); ++e2) {
671  if (e2->ambiguous())
672  continue;
673  if (ignoreNotPreselected && !isPreselected(*e2))
674  continue;
675 
676  SuperClusterRef scRef2 = e2->superCluster();
677  CaloClusterPtr eleClu2 = e2->electronCluster();
678 
679  // search if same cluster
680  bool sameCluster = false;
682  sameCluster = (scRef1 == scRef2);
683  } else if (strategyCfg_.ambClustersOverlapStrategy == 1) {
684  float eMin = 1.;
685  float threshold = eMin * cosh(EleRelPoint(scRef1->position(), beamspot.position()).eta());
686  using egamma::sharedEnergy;
687  sameCluster = ((sharedEnergy(*eleClu1, *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
688  (sharedEnergy(*scRef1->seed(), *eleClu2, barrelRecHits, endcapRecHits) >= threshold) ||
689  (sharedEnergy(*eleClu1, *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold) ||
690  (sharedEnergy(*scRef1->seed(), *scRef2->seed(), barrelRecHits, endcapRecHits) >= threshold));
691  } else {
692  throw cms::Exception("GsfElectronAlgo|UnknownAmbiguityClustersOverlapStrategy")
693  << "value of strategyCfg_.ambClustersOverlapStrategy is : " << strategyCfg_.ambClustersOverlapStrategy;
694  }
695 
696  // main instructions
697  if (sameCluster) {
698  LogDebug("GsfElectronAlgo") << "Discarding electron with E/P " << e2->eSuperClusterOverP() << ", cluster "
699  << scRef2.get() << " and track " << e2->gsfTrack().get();
700  e1->addAmbiguousGsfTrack(e2->gsfTrack());
701  e2->setAmbiguous(true);
702  } else if (e1->gsfTrack() == e2->gsfTrack()) {
703  edm::LogWarning("GsfElectronAlgo") << "Forgetting electron with E/P " << e2->eSuperClusterOverP()
704  << ", cluster " << scRef2.get() << " and track " << e2->gsfTrack().get();
705  e2->setAmbiguous(true);
706  }
707  }
708  }
709  }
710 }
711 
713  bool passCutBased = ele.passingCutBasedPreselection();
714  bool passPF = ele.passingPflowPreselection();
715  // it is worth nothing for gedGsfElectrons, this does nothing as its not set
716  // till GedGsfElectron finaliser, this is always false
717  bool passmva = ele.passingMvaPreselection();
718  if (!ele.ecalDrivenSeed()) {
719  if (ele.pt() > strategyCfg_.MaxElePtForOnlyMVA)
720  return passmva && passCutBased;
721  else
722  return passmva;
723  } else {
724  return passCutBased || passPF || passmva;
725  }
726 }
727 
728 // ------------ method called to produce the data ------------
730  // check configuration
733  auto seeds = event.getHandle(inputCfg_.seedsTag);
734  if (!seeds.isValid()) {
735  edm::LogWarning("GsfElectronAlgo|UnreachableSeedsProvenance")
736  << "Cannot check consistency of parameters with ecal seeding ones,"
737  << " because the original collection of seeds is not any more available.";
738  } else {
739  checkEcalSeedingParameters(edm::parameterSet(seeds.provenance()->stable(), event.processHistory()));
740  }
741  }
742 
743  auto electrons = algo_->completeElectrons(event, setup, globalCache());
745  const auto gsfMVAInputMap = matchWithPFCandidates(event.get(egmPFCandidateCollection_));
746  for (auto& el : electrons) {
747  el.setMvaInput(gsfMVAInputMap.find(el.gsfTrack())->second); // set Run2 MVA inputs
748  }
749  setMVAOutputs(
751  }
752 
753  // all electrons
754  logElectrons(electrons, event, "GsfElectronAlgo Info (before preselection)");
755  // preselection
757  electrons.erase(
758  std::remove_if(electrons.begin(), electrons.end(), [this](auto const& ele) { return !isPreselected(ele); }),
759  electrons.end());
760  logElectrons(electrons, event, "GsfElectronAlgo Info (after preselection)");
761  }
762  // ambiguity
765  electrons.erase(std::remove_if(electrons.begin(), electrons.end(), std::mem_fn(&reco::GsfElectron::ambiguous)),
766  electrons.end());
767  logElectrons(electrons, event, "GsfElectronAlgo Info (after amb. solving)");
768  }
769  // 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
770  if (hcalRun2EffDepth_) {
771  for (auto& ele : electrons)
772  ele.hcalToRun2EffDepth();
773  }
774  // final filling
775  event.emplace(electronPutToken_, std::move(electrons));
776 }
777 
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
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
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
ElectronHcalHelper::Configuration hcalCfg_
#define LogTrace(id)
static std::string const input
Definition: EdmProvDump.cc:47
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:198
std::vector< tensorflow::Session * > tfSessions_
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