1 |
// -*- C++ -*-
|
2 |
//
|
3 |
// Package: MuonMCClassifier
|
4 |
// Class: MuonMCClassifier
|
5 |
//
|
6 |
/**\class MuonMCClassifier MuonMCClassifier.cc PhysicsTools/PatAlgos/src/MuonMCClassifier.cc
|
7 |
|
8 |
Description: <one line class summary>
|
9 |
|
10 |
Implementation:
|
11 |
<Notes on implementation>
|
12 |
*/
|
13 |
//
|
14 |
// Original Author: Nov 16 16:12 (lxplus231.cern.ch)
|
15 |
// Created: Sun Nov 16 16:14:09 CET 2008
|
16 |
// $Id: MuonMCClassifier.cc,v 1.1 2009/04/14 13:58:52 gpetrucc Exp $
|
17 |
//
|
18 |
//
|
19 |
|
20 |
|
21 |
// system include files
|
22 |
#include <memory>
|
23 |
#include <set>
|
24 |
#include <ext/hash_map>
|
25 |
|
26 |
// user include files
|
27 |
#include "FWCore/Framework/interface/Frameworkfwd.h"
|
28 |
#include "FWCore/Framework/interface/EDProducer.h"
|
29 |
|
30 |
#include "FWCore/Framework/interface/Event.h"
|
31 |
#include "FWCore/Framework/interface/MakerMacros.h"
|
32 |
|
33 |
#include "FWCore/ParameterSet/interface/ParameterSet.h"
|
34 |
|
35 |
#include "DataFormats/Common/interface/Association.h"
|
36 |
#include "DataFormats/Common/interface/View.h"
|
37 |
#include "DataFormats/Common/interface/RefProd.h"
|
38 |
#include "DataFormats/Math/interface/deltaR.h"
|
39 |
#include "DataFormats/Candidate/interface/CandidateFwd.h"
|
40 |
#include "DataFormats/Candidate/interface/Candidate.h"
|
41 |
#include "DataFormats/HepMCCandidate/interface/GenParticleFwd.h"
|
42 |
#include "DataFormats/HepMCCandidate/interface/GenParticle.h"
|
43 |
|
44 |
//
|
45 |
// class decleration
|
46 |
class MuonMCClassifier : public edm::EDProducer {
|
47 |
public:
|
48 |
explicit MuonMCClassifier(const edm::ParameterSet&);
|
49 |
~MuonMCClassifier();
|
50 |
|
51 |
private:
|
52 |
virtual void produce(edm::Event&, const edm::EventSetup&);
|
53 |
|
54 |
/// Returns the flavour given a pdg id code
|
55 |
int flavour(int pdgId) const ;
|
56 |
|
57 |
/// Return the flavour of the first and of the heaviest ancestors of a given particle
|
58 |
std::pair<int,int> flavours(const reco::GenParticleRef & mc) const ;
|
59 |
|
60 |
/// Write a ValueMap<int> in the event
|
61 |
void writeValueMap(edm::Event &iEvent,
|
62 |
const edm::Handle<edm::View<reco::Candidate> > & handle,
|
63 |
const std::vector<int> & values,
|
64 |
const std::string & label) const ;
|
65 |
|
66 |
/// The RECO objects
|
67 |
edm::InputTag src_;
|
68 |
|
69 |
/// The GenParticle objects
|
70 |
edm::InputTag mc_;
|
71 |
|
72 |
/// The Associations
|
73 |
edm::InputTag assoHardByDr_, assoByDr_, assoByPulls_, assoInFlight_;
|
74 |
|
75 |
};
|
76 |
|
77 |
MuonMCClassifier::MuonMCClassifier(const edm::ParameterSet &iConfig) :
|
78 |
src_(iConfig.getParameter<edm::InputTag>("src")),
|
79 |
mc_(iConfig.getParameter<edm::InputTag>("mc")),
|
80 |
assoHardByDr_(iConfig.getParameter<edm::InputTag>("assoHardByDr")),
|
81 |
assoByDr_(iConfig.getParameter<edm::InputTag>("assoByDr")),
|
82 |
assoByPulls_(iConfig.getParameter<edm::InputTag>("assoByPulls")),
|
83 |
assoInFlight_(iConfig.getParameter<edm::InputTag>("assoInFlight"))
|
84 |
{
|
85 |
produces<edm::ValueMap<int> >("origin");
|
86 |
produces<edm::ValueMap<int> >("recoStatus");
|
87 |
produces<edm::ValueMap<int> >("flavourFirst");
|
88 |
produces<edm::ValueMap<int> >("flavourHeaviest");
|
89 |
}
|
90 |
|
91 |
MuonMCClassifier::~MuonMCClassifier()
|
92 |
{
|
93 |
}
|
94 |
|
95 |
void
|
96 |
MuonMCClassifier::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
|
97 |
{
|
98 |
edm::Handle<edm::View<reco::Candidate> > src;
|
99 |
iEvent.getByLabel(src_, src);
|
100 |
|
101 |
typedef std::vector<reco::GenParticle> MCColl;
|
102 |
edm::Handle<MCColl> mc;
|
103 |
iEvent.getByLabel(mc_, mc);
|
104 |
|
105 |
typedef edm::Association<MCColl> MCAssoc;
|
106 |
edm::Handle<MCAssoc> assoHardByDr, assoByDr, assoByPulls, assoInFlight;
|
107 |
iEvent.getByLabel(assoHardByDr_, assoHardByDr);
|
108 |
iEvent.getByLabel(assoByDr_, assoByDr);
|
109 |
iEvent.getByLabel(assoByPulls_, assoByPulls);
|
110 |
iEvent.getByLabel(assoInFlight_, assoInFlight);
|
111 |
|
112 |
std::vector<int> origin(src->size(), 0);
|
113 |
std::vector<int> reco( src->size(), 0);
|
114 |
std::vector<int> flavF( src->size(), 0);
|
115 |
std::vector<int> flavH( src->size(), 0);
|
116 |
|
117 |
for (size_t i = 0, n = src->size(); i < n; ++i) {
|
118 |
reco::CandidatePtr ptr = src->ptrAt(i);
|
119 |
reco::GenParticleRef mcHardByDr = (*assoHardByDr)[ptr];
|
120 |
reco::GenParticleRef mcByDr = (*assoByDr)[ptr];
|
121 |
reco::GenParticleRef mcByPulls = (*assoByPulls)[ptr];
|
122 |
reco::GenParticleRef mcInFlight = (*assoInFlight)[ptr];
|
123 |
|
124 |
if (mcHardByDr.isNonnull()) {
|
125 |
origin[i] = 1; // hard scattering muon
|
126 |
// std::cout << "Muon with pt " << ptr->pt() << " comes from hard scattering.\n";
|
127 |
flavF[i] = flavH[i] = 13;
|
128 |
} else if (mcByDr.isNonnull()) {
|
129 |
origin[i] = 2; // other generator-level decay muon
|
130 |
std::pair<int,int> flavs = flavours(mcByDr);
|
131 |
flavF[i] = flavs.first;
|
132 |
flavH[i] = flavs.second;
|
133 |
// std::cout << "Muon with pt " << ptr->pt() << " comes from primary source: flavour " << flavs.first << ", heaviest " << flavs.second << ".\n";
|
134 |
} else if (mcInFlight.isNonnull()) {
|
135 |
origin[i] = 3;
|
136 |
std::pair<int,int> flavs = flavours(mcInFlight);
|
137 |
flavF[i] = flavs.first;
|
138 |
flavH[i] = flavs.second;
|
139 |
// std::cout << "Muon with pt " << ptr->pt() << " is from in-flight decay only: flavour " << flavs.first << ", heaviest " << flavs.second << ".\n";
|
140 |
} else {
|
141 |
// std::cout << "Muon with pt " << ptr->pt() << " has undefined (non muonic) origin.\n";
|
142 |
}
|
143 |
|
144 |
switch (origin[i]) {
|
145 |
case 1:
|
146 |
case 2:
|
147 |
// bit 0 if TK reconstructed well some track
|
148 |
// bit 1 if TK reconstructed well the primary muon
|
149 |
// bit 2 if STA reconstructed the primary muon
|
150 |
reco[i] = mcByPulls.isNonnull() + 2*(mcByPulls == mcByDr) + 4*(mcInFlight == mcByDr);
|
151 |
break;
|
152 |
case 3:
|
153 |
// bit 0 if TK reconstructed well some track
|
154 |
// bit 1 if TK reconstructed well the primary muon or one of its ancestors
|
155 |
// bit 2 if STA reconstructed well the primary muon
|
156 |
reco[i] = mcByPulls.isNonnull() + 4*(mcByPulls == mcInFlight);
|
157 |
if (mcByPulls.isNonnull()) {
|
158 |
for(reco::GenParticleRef ref = mcInFlight; ref.isNonnull(); ref = ref->motherRef()) {
|
159 |
if (ref == mcByPulls) { reco[i] += 2; break; }
|
160 |
if (ref->motherRefVector().empty()) break;
|
161 |
}
|
162 |
}
|
163 |
break;
|
164 |
default:
|
165 |
// bit 0 if TK reconstructed well some track
|
166 |
reco[i] = mcByPulls.isNonnull();
|
167 |
};
|
168 |
// std::cout << " TK track matched by pulls? " << (reco[i] & 0x1 ? "Y" : "N") << std::endl;
|
169 |
// std::cout << " TK track matched correctly? " << (reco[i] & 0x2 ? "Y" : "N") << std::endl;
|
170 |
// std::cout << " ST track matched correctly? " << (reco[i] & 0x4 ? "Y" : "N") << std::endl;
|
171 |
}
|
172 |
|
173 |
writeValueMap(iEvent, src, origin, "origin");
|
174 |
writeValueMap(iEvent, src, reco, "recoStatus");
|
175 |
writeValueMap(iEvent, src, flavF, "flavourFirst");
|
176 |
writeValueMap(iEvent, src, flavH, "flavourHeaviest");
|
177 |
}
|
178 |
|
179 |
int
|
180 |
MuonMCClassifier::flavour(int pdgId) const {
|
181 |
int flav = abs(pdgId);
|
182 |
// muons and taus have themselves as flavour
|
183 |
if (flav == 13 || flav == 15) return flav;
|
184 |
// for quarks it's easy
|
185 |
if (flav <= 5) return flav;
|
186 |
// look for barions
|
187 |
int bflav = ((flav / 1000) % 10);
|
188 |
if (bflav != 0) return bflav;
|
189 |
// look for mesons
|
190 |
int mflav = ((flav / 100) % 10);
|
191 |
if (mflav != 0) return mflav;
|
192 |
return 0;
|
193 |
}
|
194 |
|
195 |
std::pair<int,int>
|
196 |
MuonMCClassifier::flavours(const reco::GenParticleRef & ref) const
|
197 |
{
|
198 |
if (ref.isNull()) return std::make_pair(0,0);
|
199 |
|
200 |
std::vector<reco::GenParticleRef> work;
|
201 |
work.insert(work.end(), ref->motherRefVector().begin(), ref->motherRefVector().end());
|
202 |
int first = -1, heaviest = 0;
|
203 |
|
204 |
while (!work.empty()) {
|
205 |
reco::GenParticleRef r = work.back(); work.pop_back();
|
206 |
int flav = flavour(r->pdgId());
|
207 |
if ((first == -1) && (flav != 0)) { first = flav; }
|
208 |
if (flav == 13 || flav == 15) {
|
209 |
if (r->status() == 3) {
|
210 |
heaviest = flav; // hard-scattering muon or tau
|
211 |
break;
|
212 |
} else {
|
213 |
flav = 0; // otherwise don't pollute the "heaviest" match
|
214 |
}
|
215 |
}
|
216 |
if (flav > heaviest) heaviest = flav;
|
217 |
work.insert(work.end(), r->motherRefVector().begin(), r->motherRefVector().end());
|
218 |
}
|
219 |
|
220 |
return std::make_pair(first,heaviest);
|
221 |
}
|
222 |
|
223 |
|
224 |
void
|
225 |
MuonMCClassifier::writeValueMap(edm::Event &iEvent,
|
226 |
const edm::Handle<edm::View<reco::Candidate> > & handle,
|
227 |
const std::vector<int> & values,
|
228 |
const std::string & label) const
|
229 |
{
|
230 |
using namespace edm;
|
231 |
using namespace std;
|
232 |
auto_ptr<ValueMap<int> > valMap(new ValueMap<int>());
|
233 |
edm::ValueMap<int>::Filler filler(*valMap);
|
234 |
filler.insert(handle, values.begin(), values.end());
|
235 |
filler.fill();
|
236 |
iEvent.put(valMap, label);
|
237 |
}
|
238 |
|
239 |
|
240 |
//define this as a plug-in
|
241 |
DEFINE_FWK_MODULE(MuonMCClassifier);
|