CMS 3D CMS Logo

LeptonFSRProducer.cc
Go to the documentation of this file.
1 
12 #include <memory>
15 
18 
21 
26 
30 
32 public:
33  explicit LeptonFSRProducer(const edm::ParameterSet& iConfig)
34  : pfcands_{consumes<pat::PackedCandidateCollection>(iConfig.getParameter<edm::InputTag>("packedPFCandidates"))},
35  electronsForVeto_{consumes<pat::ElectronCollection>(iConfig.getParameter<edm::InputTag>("slimmedElectrons"))},
36  muons_{consumes<edm::View<reco::Muon>>(iConfig.getParameter<edm::InputTag>("muons"))},
37  electrons_{consumes<edm::View<reco::GsfElectron>>(iConfig.getParameter<edm::InputTag>("electrons"))},
38  ptCutMu(iConfig.getParameter<double>("muonPtMin")),
39  etaCutMu(iConfig.getParameter<double>("muonEtaMax")),
40  ptCutE(iConfig.getParameter<double>("elePtMin")),
41  etaCutE(iConfig.getParameter<double>("eleEtaMax")),
42  photonPtCut(iConfig.getParameter<double>("photonPtMin")),
43  drEtCut(iConfig.getParameter<double>("deltaROverEt2Max")),
44  isoCut(iConfig.getParameter<double>("isolation")),
45  drSafe(0.0001) {
46  produces<std::vector<pat::GenericParticle>>();
47  produces<edm::ValueMap<int>>("muFsrIndex");
48  produces<edm::ValueMap<int>>("eleFsrIndex");
49  }
50  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
52  desc.add<edm::InputTag>("packedPFCandidates", edm::InputTag("packedPFCandidates"))
53  ->setComment("packed pf candidates where to look for photons");
54  desc.add<edm::InputTag>("slimmedElectrons", edm::InputTag("slimmedElectrons"))
55  ->setComment(
56  "electrons to check for footprint, the electron collection must have proper linking with the "
57  "packedCandidate collection");
58  desc.add<edm::InputTag>("muons", edm::InputTag("slimmedMuons"))
59  ->setComment("collection of muons to match with FSR ");
60  desc.add<edm::InputTag>("electrons", edm::InputTag("slimmedElectrons"))
61  ->setComment("collection of electrons to match with FSR ");
62  desc.add<double>("muonPtMin", 3.)->setComment("minimum pt of the muon to look for a near photon");
63  desc.add<double>("muonEtaMax", 2.4)->setComment("max eta of the muon to look for a near photon");
64  desc.add<double>("elePtMin", 5.)->setComment("minimum pt of the electron to look for a near photon");
65  desc.add<double>("eleEtaMax", 2.5)->setComment("max eta of the electron to look for a near photon");
66  desc.add<double>("photonPtMin", 2.0)->setComment("minimum photon Pt");
67  desc.add<double>("deltaROverEt2Max", 0.05)->setComment("max ratio of deltaR(lep,photon) over et2 of the photon");
68  desc.add<double>("isolation", 2.0)->setComment("photon relative isolation cut");
69 
70  descriptions.addWithDefaultLabel(desc);
71  }
72  ~LeptonFSRProducer() override = default;
73 
74 private:
75  void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
76 
79  const double& isoConeMax2,
80  const double& isoConeMin2) const;
81 
83  edm::Handle<pat::ElectronCollection> electronsForVeto) const;
84 
85  // ----------member data ---------------------------
90  const double ptCutMu;
91  const double etaCutMu;
92  const double ptCutE;
93  const double etaCutE;
94  const double photonPtCut;
95  const double drEtCut;
96  const double isoCut;
97  const double drSafe;
98 };
99 
101  using namespace std;
102 
104  iEvent.getByToken(pfcands_, pfcands);
106  iEvent.getByToken(muons_, muons);
108  iEvent.getByToken(electrons_, electrons);
109  edm::Handle<pat::ElectronCollection> electronsForVeto;
110  iEvent.getByToken(electronsForVeto_, electronsForVeto);
111 
112  // The output collection of FSR photons
113  auto fsrPhotons = std::make_unique<std::vector<pat::GenericParticle>>();
114 
115  std::vector<int> muPhotonIdxs(muons->size(), -1);
116  std::vector<double> muPhotonDRET2(muons->size(), 1e9);
117 
118  std::vector<int> elePhotonIdxs(electrons->size(), -1);
119  std::vector<double> elePhotonDRET2(electrons->size(), 1e9);
120 
121  //----------------------
122  // Loop on photon candidates
123  //----------------------
124 
125  for (auto pc = pfcands->begin(); pc != pfcands->end(); pc++) {
126  // consider only photons, with pT and eta cuts
127  if (abs(pc->pdgId()) != 22 || pc->pt() < photonPtCut || abs(pc->eta()) > 2.5)
128  continue;
129 
130  //------------------------------------------------------
131  // Get the closest lepton
132  //------------------------------------------------------
133  double dRMin(0.5);
134  int closestMu = -1;
135  int closestEle = -1;
136  double photon_relIso03 = 1e9; // computed only if necessary
137  bool skipPhoton = false;
138 
139  for (auto muon = muons->begin(); muon != muons->end(); ++muon) {
140  if (muon->pt() < ptCutMu || std::abs(muon->eta()) > etaCutMu)
141  continue;
142 
143  int muonIdx = muon - muons->begin();
144  double dR = deltaR(muon->eta(), muon->phi(), pc->eta(), pc->phi());
145  if (dR < dRMin && dR > drSafe && dR < drEtCut * pc->pt() * pc->pt()) {
146  // Check if photon is isolated
147  photon_relIso03 = computeRelativeIsolation(*pc, *pfcands, 0.3 * 0.3, drSafe * drSafe);
148  if (photon_relIso03 > isoCut) {
149  skipPhoton = true;
150  break; // break loop on muons -> photon will be skipped
151  }
152  // Check that photon is not in footprint of an electron
154  skipPhoton = electronFootprintVeto(pfcandRef, electronsForVeto);
155  if (skipPhoton)
156  break; // break loop on muons -> photon will be skipped
157 
158  // Candidate matching
159  dRMin = dR;
160  closestMu = muonIdx;
161  }
162  } // end of loop on muons
163 
164  if (skipPhoton)
165  continue; // photon does not pass iso or ele footprint veto; do not look for electrons
166 
167  for (auto ele = electrons->begin(); ele != electrons->end(); ++ele) {
168  if (ele->pt() < ptCutE || std::abs(ele->eta()) > etaCutE)
169  continue;
170 
171  int eleIdx = ele - electrons->begin();
172  double dR = deltaR(ele->eta(), ele->phi(), pc->eta(), pc->phi());
173  if (dR < dRMin && dR > drSafe && dR < drEtCut * pc->pt() * pc->pt()) {
174  // Check if photon is isolated (no need to recompute iso if already done for muons above)
175  if (photon_relIso03 > 1e8) {
176  photon_relIso03 = computeRelativeIsolation(*pc, *pfcands, 0.3 * 0.3, drSafe * drSafe);
177  }
178  if (photon_relIso03 > isoCut) {
179  break; // break loop on electrons -> photon will be skipped
180  }
181  // Check that photon is not in footprint of an electron
183  if (electronFootprintVeto(pfcandRef, electronsForVeto)) {
184  break; // break loop on electrons -> photon will be skipped
185  }
186 
187  // Candidate matching
188  dRMin = dR;
189  closestEle = eleIdx;
190  closestMu = -1; // reset match to muons
191  }
192  } // end loop on electrons
193 
194  if (closestMu >= 0 || closestEle >= 0) {
195  // Add FSR photon to the output collection
196  double dRET2 = dRMin / pc->pt() / pc->pt();
197  int iPhoton = fsrPhotons->size();
198  fsrPhotons->push_back(pat::GenericParticle(*pc));
199  fsrPhotons->back().addUserFloat("relIso03", photon_relIso03);
200  fsrPhotons->back().addUserFloat("dROverEt2", dRET2);
201 
202  if (closestMu >= 0) {
203  fsrPhotons->back().addUserCand("associatedMuon", reco::CandidatePtr(muons, closestMu));
204  // Store the backlink to the photon: choose the lowest-dRET2 photon for each mu...
205  if (dRET2 < muPhotonDRET2[closestMu]) {
206  muPhotonDRET2[closestMu] = dRET2;
207  muPhotonIdxs[closestMu] = iPhoton;
208  }
209  } else if (closestEle >= 0) {
210  // ...and same for eles
211  fsrPhotons->back().addUserCand("associatedElectron", reco::CandidatePtr(electrons, closestEle));
212  if (dRET2 < elePhotonDRET2[closestEle]) {
213  elePhotonDRET2[closestEle] = dRET2;
214  elePhotonIdxs[closestEle] = iPhoton;
215  }
216  }
217  }
218  } // end of loop over pfCands
219 
221 
222  {
223  std::unique_ptr<edm::ValueMap<int>> bareIdx(new edm::ValueMap<int>());
224  edm::ValueMap<int>::Filler fillerBareIdx(*bareIdx);
225  fillerBareIdx.insert(muons, muPhotonIdxs.begin(), muPhotonIdxs.end());
226  fillerBareIdx.fill();
227  iEvent.put(std::move(bareIdx), "muFsrIndex");
228  }
229 
230  {
231  std::unique_ptr<edm::ValueMap<int>> bareIdx(new edm::ValueMap<int>());
232  edm::ValueMap<int>::Filler fillerBareIdx(*bareIdx);
233  fillerBareIdx.insert(electrons, elePhotonIdxs.begin(), elePhotonIdxs.end());
234  fillerBareIdx.fill();
235  iEvent.put(std::move(bareIdx), "eleFsrIndex");
236  }
237 }
238 
241  const double& isoConeMax2,
242  const double& isoConeMin2) const {
243  double ptsum = 0;
244 
245  for (const auto& pfcand : pfcands) {
246  // Isolation cone
247  double dRIsoCone2 = deltaR2(photon.eta(), photon.phi(), pfcand.eta(), pfcand.phi());
248  if (dRIsoCone2 > isoConeMax2 || dRIsoCone2 < isoConeMin2)
249  continue;
250 
251  // Charged hadrons
252  if (pfcand.charge() != 0 && abs(pfcand.pdgId()) == 211 && pfcand.pt() > 0.2 && dRIsoCone2 > drSafe * drSafe) {
253  ptsum += pfcand.pt();
254  // Neutral hadrons + photons
255  } else if (pfcand.charge() == 0 && (abs(pfcand.pdgId()) == 22 || abs(pfcand.pdgId()) == 130) && pfcand.pt() > 0.5 &&
256  dRIsoCone2 > 0.01 * 0.01) {
257  ptsum += pfcand.pt();
258  }
259  }
260 
261  return ptsum / photon.pt();
262 }
263 
265  edm::Handle<pat::ElectronCollection> electronsForVeto) const {
266  bool skipPhoton = false;
267  for (auto electrons_iter = electronsForVeto->begin(); electrons_iter != electronsForVeto->end(); ++electrons_iter) {
268  for (auto const& cand : electrons_iter->associatedPackedPFCandidates()) {
269  if (!cand.isAvailable())
270  continue;
271  if (cand.id() != pfcandRef.id())
272  throw cms::Exception("Configuration")
273  << "The electron associatedPackedPFCandidates item does not have "
274  << "the same ID of packed candidate collection used for cleaning the electron footprint: " << cand.id()
275  << " (" << pfcandRef.id() << ")\n";
276  if (cand.key() == pfcandRef.key()) {
277  skipPhoton = true;
278  break;
279  }
280  }
281  }
282  return skipPhoton;
283 }
284 
285 //define this as a plug-in
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
ProductID id() const
Accessor for product ID.
Definition: Ref.h:244
double computeRelativeIsolation(const pat::PackedCandidate &photon, const pat::PackedCandidateCollection &pfcands, const double &isoConeMax2, const double &isoConeMin2) const
void produce(edm::StreamID, edm::Event &, const edm::EventSetup &) const override
std::vector< pat::PackedCandidate > PackedCandidateCollection
void insert(const H &h, I begin, I end)
Definition: ValueMap.h:53
const edm::EDGetTokenT< pat::PackedCandidateCollection > pfcands_
bool electronFootprintVeto(pat::PackedCandidateRef &pfcandRef, edm::Handle< pat::ElectronCollection > electronsForVeto) const
key_type key() const
Accessor for product key.
Definition: Ref.h:250
const double photonPtCut
Analysis-level Generic Particle class (e.g. for hadron or muon not fully reconstructed) ...
~LeptonFSRProducer() override=default
int iEvent
Definition: GenABIO.cc:224
edm::Ref< pat::PackedCandidateCollection > PackedCandidateRef
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
const edm::EDGetTokenT< edm::View< reco::Muon > > muons_
const edm::EDGetTokenT< pat::ElectronCollection > electronsForVeto_
LeptonFSRProducer(const edm::ParameterSet &iConfig)
def move(src, dest)
Definition: eostools.py:511
const edm::EDGetTokenT< edm::View< reco::GsfElectron > > electrons_