CMS 3D CMS Logo

MuonFSRProducer.cc
Go to the documentation of this file.
1 // system include files
2 #include <memory>
3 
4 // user include files
7 
10 
13 
18 
21 
22 //
23 // class declaration
24 //
25 
27 public:
28  explicit MuonFSRProducer(const edm::ParameterSet& iConfig)
29  :
30 
31  pfcands_{consumes<pat::PackedCandidateCollection>(iConfig.getParameter<edm::InputTag>("packedPFCandidates"))},
32  electrons_{consumes<pat::ElectronCollection>(iConfig.getParameter<edm::InputTag>("slimmedElectrons"))},
33  muons_{consumes<edm::View<reco::Muon>>(iConfig.getParameter<edm::InputTag>("muons"))},
34  ptCut(iConfig.getParameter<double>("muonPtMin")),
35  etaCut(iConfig.getParameter<double>("muonEtaMax")),
36  photonPtCut(iConfig.getParameter<double>("photonPtMin")),
37  drEtCut(iConfig.getParameter<double>("deltaROverEt2Max")),
38  isoCut(iConfig.getParameter<double>("isolation")) {
39  produces<std::vector<pat::GenericParticle>>();
40  }
41  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
43  desc.add<edm::InputTag>("packedPFCandidates", edm::InputTag("packedPFCandidates"))
44  ->setComment("packed pf candidates where to look for photons");
45  desc.add<edm::InputTag>("slimmedElectrons", edm::InputTag("slimmedElectrons"))
46  ->setComment(
47  "electrons to check for footprint, the electron collection must have proper linking with the "
48  "packedCandidate collection");
49  desc.add<edm::InputTag>("muons", edm::InputTag("slimmedMuons"))
50  ->setComment("collection of muons to correct for FSR ");
51  desc.add<double>("muonPtMin", 20.)->setComment("minimum pt of the muon to look for a near photon");
52  desc.add<double>("muonEtaMax", 2.4)->setComment("max eta of the muon to look for a near photon");
53  desc.add<double>("photonPtMin", 2.0)->setComment("minimum photon Pt");
54  desc.add<double>("deltaROverEt2Max", 0.05)->setComment("max ratio of deltsR(mu,photon) over et2 of the photon");
55  desc.add<double>("isolation", 2.0)->setComment("relative isolation cut");
56 
57  descriptions.addWithDefaultLabel(desc);
58  }
59  ~MuonFSRProducer() override {}
60 
61 private:
62  void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
63 
66  const double& isoConeMax,
67  const double& isoConeMin) const;
68 
69  // ----------member data ---------------------------
73  float ptCut;
74  float etaCut;
75  float photonPtCut;
76  float drEtCut;
77  float isoCut;
78 };
79 
81  using namespace std;
82 
84  iEvent.getByToken(pfcands_, pfcands);
86  iEvent.getByToken(muons_, muons);
88  iEvent.getByToken(electrons_, electrons);
89 
90  auto fsrPhotons = std::make_unique<std::vector<pat::GenericParticle>>();
91  // loop over all muons
92  for (auto muon = muons->begin(); muon != muons->end(); ++muon) {
93  int photonPosition = -1;
94  double distance_metric_min = -1;
95  // minimum muon pT
96  if (muon->pt() < ptCut)
97  continue;
98  // maximum muon eta
99  if (abs(muon->eta()) > etaCut)
100  continue;
101 
102  // for each muon, loop over all pf cadidates
103  for (auto iter_pf = pfcands->begin(); iter_pf != pfcands->end(); iter_pf++) {
104  auto const& pc = *iter_pf;
105 
106  // consider only photons
107  if (abs(pc.pdgId()) != 22)
108  continue;
109  // minimum pT cut
110  if (pc.pt() < photonPtCut)
111  continue;
112 
113  // eta requirements
114  if (abs(pc.eta()) > 1.4 and (abs(pc.eta()) < 1.6))
115  continue;
116  if (abs(pc.eta()) > 2.5)
117  continue;
118 
119  // 0.0001 < DeltaR(photon,muon) < 0.5 requirement
120  double dRPhoMu = deltaR(muon->eta(), muon->phi(), pc.eta(), pc.phi());
121  if (dRPhoMu < 0.0001)
122  continue;
123  if (dRPhoMu > 0.5)
124  continue;
125 
126  bool skipPhoton = false;
127  bool closest = true;
128 
129  for (auto othermuon = muons->begin(); othermuon != muons->end(); ++othermuon) {
130  if (othermuon->pt() < ptCut or abs(othermuon->eta()) > etaCut or muon == othermuon)
131  continue;
132  double dRPhoMuOther = deltaR(othermuon->eta(), othermuon->phi(), pc.eta(), pc.phi());
133  if (dRPhoMuOther < dRPhoMu) {
134  closest = false;
135  break;
136  }
137  }
138  if (!closest)
139  continue;
140 
141  // Check that is not in footprint of an electron
142  pat::PackedCandidateRef pfcandRef = pat::PackedCandidateRef(pfcands, iter_pf - pfcands->begin());
143 
144  for (auto electrons_iter = electrons->begin(); electrons_iter != electrons->end(); ++electrons_iter) {
145  for (auto const& cand : electrons_iter->associatedPackedPFCandidates()) {
146  if (!cand.isAvailable())
147  continue;
148  if (cand.id() != pfcandRef.id())
149  throw cms::Exception("Configuration")
150  << "The electron associatedPackedPFCandidates item does not have "
151  << "the same ID of packed candidate collection used for cleaning the electron footprint: " << cand.id()
152  << " (" << pfcandRef.id() << ")\n";
153  if (cand.key() == pfcandRef.key()) {
154  skipPhoton = true;
155  break;
156  }
157  }
158  if (skipPhoton)
159  break;
160  }
161 
162  if (skipPhoton)
163  continue;
164 
165  // use only isolated photons (very loose prelection can be tightened on analysis level)
166  float photon_relIso03 = computeRelativeIsolation(pc, *pfcands, 0.3, 0.0001);
167  if (photon_relIso03 > isoCut)
168  continue;
169  double metric = deltaR(muon->eta(), muon->phi(), pc.eta(), pc.phi()) / (pc.pt() * pc.pt());
170  if (metric > drEtCut)
171  continue;
172  fsrPhotons->push_back(pat::GenericParticle(pc));
173  fsrPhotons->back().addUserFloat("relIso03", photon_relIso03); // isolation, no CHS
174  fsrPhotons->back().addUserCand("associatedMuon", reco::CandidatePtr(muons, muon - muons->begin()));
175  fsrPhotons->back().addUserFloat("dROverEt2", metric); // dR/et2 to the closest muon
176 
177  // FSR photon defined as the one with minimum value of DeltaR/Et^2
178  if (photonPosition == -1 or metric < distance_metric_min) {
179  distance_metric_min = metric;
180  photonPosition = fsrPhotons->size() - 1;
181  }
182  }
183  }
184 
186 }
187 
190  const double& isoConeMax,
191  const double& isoConeMin) const {
192  double ptsum = 0;
193 
194  for (const auto& pfcand : pfcands) {
195  // Isolation cone requirement
196  double dRIsoCone = deltaR(photon.eta(), photon.phi(), pfcand.eta(), pfcand.phi());
197  if (dRIsoCone > isoConeMax)
198  continue;
199  if (dRIsoCone < isoConeMin)
200  continue;
201 
202  if (pfcand.charge() != 0 && abs(pfcand.pdgId()) == 211 && pfcand.pt() > 0.2) {
203  if (dRIsoCone > 0.0001)
204  ptsum += pfcand.pt();
205  } else if (pfcand.charge() == 0 && (abs(pfcand.pdgId()) == 22 || abs(pfcand.pdgId()) == 130) && pfcand.pt() > 0.5) {
206  if (dRIsoCone > 0.01)
207  ptsum += pfcand.pt();
208  }
209  }
210 
211  return ptsum / photon.pt();
212 }
213 
214 //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
~MuonFSRProducer() override
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
std::vector< pat::PackedCandidate > PackedCandidateCollection
const edm::EDGetTokenT< pat::PackedCandidateCollection > pfcands_
double computeRelativeIsolation(const pat::PackedCandidate &photon, const pat::PackedCandidateCollection &pfcands, const double &isoConeMax, const double &isoConeMin) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
key_type key() const
Accessor for product key.
Definition: Ref.h:250
Analysis-level Generic Particle class (e.g. for hadron or muon not fully reconstructed) ...
int iEvent
Definition: GenABIO.cc:224
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
edm::Ref< pat::PackedCandidateCollection > PackedCandidateRef
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void produce(edm::StreamID, edm::Event &, const edm::EventSetup &) const override
MuonFSRProducer(const edm::ParameterSet &iConfig)
const edm::EDGetTokenT< edm::View< reco::Muon > > muons_
const edm::EDGetTokenT< pat::ElectronCollection > electrons_
def move(src, dest)
Definition: eostools.py:511