ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/HbbAnalysis/src/JetFlavour.cc
Revision: 1.9
Committed: Thu Mar 17 12:47:39 2011 UTC (14 years, 1 month ago) by amagnan
Content type: text/plain
Branch: MAIN
CVS Tags: v01-00-00, beforeMETHacks, v00-05-03, v00-05-02, HEAD
Changes since 1.8: +2 -2 lines
Log Message:
JEC

File Contents

# Content
1 #include <iostream>
2 #include <fstream>
3
4 #include "Math/VectorUtil.h"
5
6 #include "UserCode/HbbAnalysis/interface/JetFlavour.hh"
7
8 namespace HbbAnalysis {
9
10 void JetFlavour::Initialise(TFileDirectory & aDir, unsigned short aDebug, unsigned int aFlavour){
11
12 debug_ = aDebug;
13 flavour_ = aFlavour;
14
15 partons_.clear();
16 flav_.clear();
17 eid_.clear();
18 muid_.clear();
19
20 p_nQuarks = aDir.make<TH1F>("p_nQuarks",";n_{q};N_{entries}",10,0,10);
21 p_nAntiQuarks = aDir.make<TH1F>("p_nAntiQuarks",";n_{#bar{q}};N_{entries}",10,0,10);
22 p_partonFlavour = aDir.make<TH1F>("p_partonFlavour",";pdgId of initial parton;N_{entries}",28,-6,22);
23 p_parentOfStableFlavour = aDir.make<TH1F>("p_parentOfStableFlavour",";pdgId of parent of stable particle;N_{entries}",12000,-6000,6000);
24 p_stableFlavour = aDir.make<TH1F>("p_stableFlavour",";pdgId of stable particle;N_{entries}",2000,-1000,1000);
25 p_numberOfParentsOfStable = aDir.make<TH1F>("p_numberOfParentsOfStable",";number of parents of stable particle;N_{entries}",50,0,50);
26
27
28 nTot_ = 0;
29 nLight_ = 0;
30 nGluon_ = 0;
31 nCharm_ = 0;
32 nBottom_ = 0;
33 nTotal_ = 0;
34 nHeavy_ = 0;
35 nSemiHeavy_ = 0;
36
37 nZEvts_ = 0;
38 nWEvts_ = 0;
39
40 if (debug_) std::cout << " --- JetFlavour::Initialise success ! " << std::endl;
41
42 }
43
44 unsigned int JetFlavour::fillPartons(const edm::Handle<reco::GenParticleCollection> & aGenParticles) {//genMatching
45
46 nTot_++;
47
48 partons_.clear();
49 flav_.clear();
50 eid_.clear();
51 muid_.clear();
52 partons_.reserve(2);
53 eid_.reserve(2);
54 muid_.reserve(2);
55 flav_.reserve(2);
56
57 unsigned int n_quarks = 0;
58 unsigned int n_antiquarks = 0;
59
60 bool isZ = false;
61 bool isW = false;
62
63 unsigned int lNMC = aGenParticles->size();
64
65 if (debug_) std::cout << "* nMC = " << lNMC << std::endl;
66
67 //loop on MC part to find any initial partons.
68 for (unsigned int imc(0); imc < lNMC; imc++){//loop on MC particles
69 const reco::GenParticle & lPart = (*aGenParticles).at(imc);
70 //break loop if W events
71 //for QCD, it should never fullfill these criteria anyway....
72 if ( lPart.status() == 3 && lPart.numberOfMothers() > 1 &&
73 ( abs(lPart.pdgId()) == 24 ||
74 abs(lPart.pdgId()) == 12 ||
75 abs(lPart.pdgId()) == 14 ||
76 abs(lPart.pdgId()) == 16 ) ) {
77 isW = true;
78 nWEvts_++;
79 //if (!isZ) break;
80 }
81 //record when Z event
82 if ( lPart.status() == 3 && lPart.numberOfMothers() > 1 &&
83 ( abs(lPart.pdgId()) == 23 ||
84 lPart.pdgId() == 11 ||
85 lPart.pdgId() == 13 ||
86 lPart.pdgId() == 15 ) ) {
87 isZ = true;
88 nZEvts_++;
89 }
90 //looking for the final-states partons, which will have 2 parents being the 2 initial states partons.
91 if (lPart.status() == 3 && lPart.numberOfMothers() > 1 &&
92 ( ( flavour_ == 45 && (abs(lPart.pdgId()) == 4 || abs(lPart.pdgId()) == 5) ) ||
93 ( flavour_ > 3 && flavour_ < 22 && static_cast<unsigned int>(abs(lPart.pdgId())) == flavour_) ||
94 ( flavour_ == 3 && ( (static_cast<unsigned int>(abs(lPart.pdgId())) <= flavour_ ||
95 lPart.pdgId() == 21)
96 )
97 )
98 )
99 ) {
100 if (debug_ > 1) {
101 std::cout << "** initial parton #" << imc ;
102 printParticle(lPart);
103 }
104 partons_.push_back(imc);
105 if (lPart.pdgId() > 0) n_quarks++;
106 else n_antiquarks++;
107 p_partonFlavour->Fill(lPart.pdgId());
108 }
109 else if ((debug_ > 1 && imc < 15) || debug_ > 2) {
110 std::cout << "** not selected: #" << imc;
111 printParticle(lPart);
112 }
113
114 }//loop on MC particles
115
116 //if (isW == isZ) std::cout << "*** WARNING *** isW = " << isW << ", isZ = " << isZ << std::endl;
117 //if ((flavour_ > 3 && flavour_ != 21) && !isZ) return 0;
118
119 if (debug_) {
120 std::cout << "nQuarks = " << n_quarks << ", n_antiQuarks = " << n_antiquarks << std::endl;
121 std::cout << "nPartons = " << partons_.size() << " with indices " << std::endl;
122 for (unsigned int ip(0); ip<partons_.size();ip++){
123 std::cout << "#" << partons_.at(ip) << ": " ;
124 printParticle(parton(aGenParticles,ip));
125 }
126 }
127
128 const unsigned int nPartons = partons_.size();
129
130 if (nPartons == 0) {
131 nHeavy_++;
132 return 0;
133 }
134 if (nPartons == 1) nSemiHeavy_++;
135
136 nTotal_ += nPartons;
137 assert (nPartons == n_quarks+n_antiquarks);
138
139 // if (flavour_ > 3) {
140 // assert(n_quarks >= 1 && n_antiquarks >= 1);
141 // assert (nPartons == 2);
142 // }
143
144 p_nQuarks->Fill(n_quarks);
145 p_nAntiQuarks->Fill(n_antiquarks);
146
147
148 //loop on MC to find partons daughters
149 unsigned int *nDaugh = new unsigned int[nPartons];
150 //vectors of indices of parents/daughters
151 //indices with respect to initial genParticle collection (always read in the same order)
152 std::vector<unsigned int> *parents = new std::vector<unsigned int>[nPartons];
153 std::vector<unsigned int> *daughters = new std::vector<unsigned int>[nPartons];
154
155 unsigned int *flav = new unsigned int[nPartons];
156
157 //indices of stable electron/muon, if any
158 unsigned int *eid = new unsigned int[nPartons];
159 unsigned int *muid = new unsigned int[nPartons];
160
161 for (unsigned int ip(0); ip<nPartons; ip++){//loop on partons
162 nDaugh[ip] = 0;
163 flav[ip] = 1;
164 if (flavour_ == 3 || flavour_ == 21){
165 if (parton(aGenParticles,ip).pdgId() == 21) flav[ip] = 3;
166 else flav[ip] = 2;
167 }
168 eid[ip] = 0;
169 muid[ip] = 0;
170 daughters[ip].clear();
171 daughters[ip].reserve(500);
172 parents[ip].clear();
173 parents[ip].reserve(500);
174 parents[ip].push_back(partons_.at(ip));
175
176 for (unsigned int pmc = 0; pmc < parents[ip].size(); pmc++){//loop "interactively" on parents
177 unsigned int lParIndex = parents[ip].at(pmc);
178 const reco::GenParticle & ppar = (*aGenParticles).at(lParIndex);
179 if (debug_ > 2) std::cout << "** Looking for parent : #" << lParIndex << " (id " << ppar.pdgId() << "), vector size = " << parents[ip].size() << std::endl;
180
181 //counter to check a match is found
182 unsigned int lNNotFound = 0;
183 unsigned int lNTot = 0;
184
185 for (unsigned int imc(0); imc < lNMC; imc++){//loop on parts
186 const reco::GenParticle & pgen = (*aGenParticles).at(imc);
187
188 for (unsigned int im(0); im<pgen.numberOfMothers(); im++){//loop on parents
189 //recursive loop to find all parents
190 if ( compareParticles(pgen.mother(im),ppar)){//if par=parton
191 lNTot++;
192 if (pgen.status() != 1) {
193 nDaugh[ip]++;
194 if (debug_ > 2) {
195 std::cout << "*** b daughter #" << nDaugh[ip] << " : " << imc ;
196 printParticle(pgen);
197 }
198 //to recursively account for every possible parent until the last stable particles...
199 if (std::find(parents[ip].begin(),parents[ip].end(),imc)==parents[ip].end()) parents[ip].push_back(imc);
200 }
201 else {
202 nDaugh[ip]++;
203 if (debug_ > 2) {
204 std::cout << "*** b stable daughter #" << nDaugh[ip] << " : " << imc;
205 printParticle(pgen);
206 }
207 if (std::find(daughters[ip].begin(),daughters[ip].end(),imc)==daughters[ip].end()) {
208 daughters[ip].push_back(imc);
209 p_stableFlavour->Fill(pgen.pdgId());
210 p_numberOfParentsOfStable->Fill(pgen.numberOfMothers());
211 p_parentOfStableFlavour->Fill(pgen.mother(0)->pdgId());
212 if (fabs(pgen.pdgId()) == 11) {
213 assert(pgen.numberOfMothers() == 1);
214 }
215 else if (fabs(pgen.pdgId()) == 13) {
216 assert(pgen.numberOfMothers() == 1);
217 }
218 }
219 }
220 }//if par=parton
221 else {
222 lNNotFound++;
223 lNTot++;
224 }
225 }//loop on parents
226
227 }//loop on parts
228 if (lNNotFound == lNTot ) {
229 std::cout << " --- WARNING: no particle found for parton #" << lParIndex ;
230 printParticle(ppar);
231 }
232
233 }//loop on parents
234
235 //loop on daughters to find e/mu coming from B and D mesons only
236 //and associate flav=2 if b,c decay into e, 3 if mu
237
238 if (flavour_ > 3 && flavour_ != 21){//for b and c jets
239 if (abs(parton(aGenParticles,ip).pdgId()) == 4) nCharm_++;
240 else nBottom_++;
241 for (unsigned int dmc = 0; dmc < daughters[ip].size(); dmc++){//loop on daughters
242 const reco::GenParticle & pgen = (*aGenParticles).at(daughters[ip].at(dmc));
243 if (fabs(pgen.pdgId()) == 11 && pgen.numberOfMothers() > 1) std::cout << "***WARNING*** b Electron has more than one parent !! : " << pgen.numberOfMothers() << std::endl;
244 if (fabs(pgen.pdgId()) == 13 && pgen.numberOfMothers() > 1) std::cout << "***WARNING*** b Muon has more than one parent !! : " << pgen.numberOfMothers() << std::endl;
245 if (fabs(pgen.pdgId()) == 11 && pgen.numberOfMothers() == 1 && ((fabs(pgen.mother(0)->pdgId()) > 400 && fabs(pgen.mother(0)->pdgId()) < 600) || fabs(pgen.mother(0)->pdgId()) > 4000))
246 {
247 flav[ip] = 2;
248 eid[ip] = daughters[ip].at(dmc);
249
250 break;
251 }
252 if (fabs(pgen.pdgId()) == 13 && pgen.numberOfMothers() == 1 && ((fabs(pgen.mother(0)->pdgId()) > 400 && fabs(pgen.mother(0)->pdgId()) < 600) || fabs(pgen.mother(0)->pdgId()) > 4000))
253 {
254 flav[ip] = 3;
255 muid[ip] = daughters[ip].at(dmc);
256 break;
257 }
258 }//loop on daughters
259
260 flav_.push_back(flav[ip]);
261 eid_.push_back(eid[ip]);
262 muid_.push_back(muid[ip]);
263
264 }//for b and c jets
265
266
267 if (parents[ip].size() > 500) std::cout << "WARNING ! Initial default size of parents not sufficient = " << parents[ip].size() << std::endl;
268 if (daughters[ip].size() > 500) std::cout << "WARNING ! Initial default size of daughters not sufficient = " << daughters[ip].size() << std::endl;
269
270
271 }//loop on partons
272
273 //reject QCD if B or C in the decay chain
274 if (flavour_ == 3 || flavour_ == 21){//for light jets
275 int pp = 0;
276 for (std::vector<unsigned int>::iterator lPart = partons_.begin(); lPart!= partons_.end(); lPart++){//loop on partons
277 bool isHeavy = false;
278 for (unsigned int dmc = 0; dmc < daughters[pp].size(); dmc++){//loop on daughters
279 const reco::GenParticle & pgen = (*aGenParticles).at(daughters[pp].at(dmc));
280
281 if (abs(pgen.pdgId()) == 4 || abs(pgen.pdgId()) == 5) {
282 //if (debug_ > 2)
283 std::cout << "*** Found daughter with pdgId = " << pgen.pdgId() << " in decay chain of parton #" << pp << ", deleting from partons vector and going to next parton." << std::endl;
284 if (abs(pgen.pdgId()) == 4) nCharm_++;
285 else nBottom_++;
286 isHeavy = true;
287 partons_.erase(lPart);
288 break;
289 }
290 }//loop on daughters
291 if (!isHeavy) {
292 flav_.push_back(flav[pp]);
293 //to ensure all vectors have the same size...
294 eid_.push_back(0);
295 muid_.push_back(0);
296
297 if (flav[pp] == 3) nGluon_++;
298 else nLight_++;
299 }
300 pp++;
301
302 }//loop on partons
303
304 }//for light jets
305
306
307 delete[] nDaugh;
308 delete[] parents;
309 delete[] daughters;
310 delete[] flav;
311 delete[] eid;
312 delete[] muid;
313
314 return nPartons;
315
316
317 }//fillPartons
318
319
320 const std::pair<int,unsigned int> JetFlavour::partonMatchingGenJet(const pat::Jet & aJet, const edm::Handle<reco::GenParticleCollection> & aGenParticles, const double aDR) const{//parton match with gen jet
321
322 int aIndex = -1;
323 double deltaRMin = 1000;
324
325 if (!aJet.genJet()) return std::pair<int,unsigned int>(aIndex,0);
326
327 for (unsigned int lPart(0); lPart<nPartons(); lPart++){
328 double lDR = ROOT::Math::VectorUtil::DeltaR(parton(aGenParticles,lPart).p4(),aJet.genJet()->p4());
329 if (lDR < deltaRMin) {
330 deltaRMin = lDR;
331 aIndex = lPart;
332 }
333 }
334
335 if (deltaRMin < aDR) return std::pair<int,unsigned int>(aIndex,partonFlavour(aIndex));
336 else return std::pair<int,unsigned int>(aIndex,0);
337
338 }//parton match with gen jet
339
340 const unsigned int JetFlavour::leptonMatchingGenJet(const pat::Jet & aJet, const edm::Handle<reco::GenParticleCollection> & aGenParticles, const double aDR) const{//lepton match with gen jet
341
342 int aIndex = -1;
343 double deltaRMin = 1000;
344
345 if (!aJet.genJet()) return 0;
346
347 if (flavour_ > 3 && flavour_ != 21) {
348 for (unsigned int lPart(0); lPart<nPartons(); lPart++){
349 if (eid_.at(lPart)){
350 double lDR = ROOT::Math::VectorUtil::DeltaR(stableElectron(aGenParticles,lPart).p4(),aJet.genJet()->p4());
351 if (lDR < deltaRMin) {
352 deltaRMin = lDR;
353 aIndex = lPart;
354 }
355 }
356 else if (muid_.at(lPart)){
357 double lDR = ROOT::Math::VectorUtil::DeltaR(stableMuon(aGenParticles,lPart).p4(),aJet.genJet()->p4());
358 if (lDR < deltaRMin) {
359 deltaRMin = lDR;
360 aIndex = lPart;
361 }
362 }
363 if (eid_.at(lPart) && muid_.at(lPart)) {
364 std::cerr << " ---- Problem !! found electron and muon for parton ";
365 printParticle(parton(aGenParticles,lPart));
366 }
367 }
368
369 if (deltaRMin < aDR) return partonFlavour(aIndex);
370 else return 0;
371 }
372 else return 0;
373
374 }//lepton match with gen jet
375
376 const unsigned int JetFlavour::partonMatchingRecoJet(const pat::Jet & aJet, const edm::Handle<reco::GenParticleCollection> & aGenParticles, const double aDR) const{//parton match with reco jet
377
378 int aIndex = -1;
379 double deltaRMin = 1000;
380
381 for (unsigned int lPart(0); lPart<nPartons(); lPart++){
382 double lDR = ROOT::Math::VectorUtil::DeltaR(parton(aGenParticles,lPart).p4(),aJet.p4());
383 if (lDR < deltaRMin) {
384 deltaRMin = lDR;
385 aIndex = lPart;
386 }
387 }
388
389 if (deltaRMin < aDR) return partonFlavour(aIndex);
390 else return 0;
391
392 }//parton match with reco jet
393
394 const unsigned int JetFlavour::leptonMatchingRecoJet(const pat::Jet & aJet, const edm::Handle<reco::GenParticleCollection> & aGenParticles, const double aDR) const{//lepton match with reco jet
395
396 int aIndex = -1;
397 double deltaRMin = 1000;
398
399 if (flavour_ > 3 && flavour_ != 21) {
400 for (unsigned int lPart(0); lPart<nPartons(); lPart++){
401 if (eid_.at(lPart)){
402 double lDR = ROOT::Math::VectorUtil::DeltaR(stableElectron(aGenParticles,lPart).p4(),aJet.p4());
403 if (lDR < deltaRMin) {
404 deltaRMin = lDR;
405 aIndex = lPart;
406 }
407 }
408 else if (muid_.at(lPart)){
409 double lDR = ROOT::Math::VectorUtil::DeltaR(stableMuon(aGenParticles,lPart).p4(),aJet.p4());
410 if (lDR < deltaRMin) {
411 deltaRMin = lDR;
412 aIndex = lPart;
413 }
414 }
415 if (eid_.at(lPart) && muid_.at(lPart)) {
416 std::cerr << " ---- Problem !! found electron and muon for parton ";
417 printParticle(parton(aGenParticles,lPart));
418 }
419 }
420
421 if (deltaRMin < aDR) return partonFlavour(aIndex);
422 else return 0;
423 }
424 else return 0;
425
426 }//lepton match with reco jet
427
428 bool JetFlavour::compareParticles(const reco::Candidate * aMum, const reco::GenParticle & aP)
429 {
430
431 if (!aMum) return false;
432 if ( aMum->pdgId() == aP.pdgId() &&
433 aMum->status() == aP.status() &&
434 aMum->pt() >= aP.pt()-0.001 && aMum->pt() <= aP.pt()+0.001 &&
435 ROOT::Math::VectorUtil::DeltaR(aMum->p4(),aP.p4()) < 0.001 )
436 return true;
437
438 return false;
439 }
440
441 void JetFlavour::printParticle(const reco::GenParticle & aP) const{
442 std::cout << " HistosJets::printParticle: " << std::endl <<
443 " ---- pid = " << aP.pdgId() << std::endl <<
444 " ---- status = " << aP.status() << std::endl <<
445 " ---- charge = " << aP.charge() << std::endl <<
446 " ---- pt = " << aP.pt() << std::endl <<
447 //" ---- eta = " << eta_ << std::endl <<
448 //" ---- phi = " << phi_ << std::endl <<
449 //" ---- vertex = " << vx_ << " " << vy_ << " " << vz_ << std::endl <<
450 " ---- parents : " << aP.numberOfMothers() << ". IDs,status = " ;
451 for (unsigned int ip(0); ip<aP.numberOfMothers(); ip++){
452 std::cout << aP.mother(ip)->pdgId() << "," << aP.mother(ip)->status() << " ";
453 }
454 std::cout << std::endl;
455
456 }
457
458 void JetFlavour::printSummary() const{
459
460 std::cout <<
461 "=====================================================================" << std::endl <<
462 "======== Summary: " << std::endl <<
463 "======== Looking for partons with flavour = " << flavour_ << std::endl <<
464 "=====================================================================" << std::endl <<
465 "**** total = " << nTot_ << " events," << std::endl <<
466 "**** Z events = " << nZEvts_ << ", W events = " << nWEvts_ << std::endl <<
467 "**** discarded " << nHeavy_ << " Z events with no selected partons," << std::endl <<
468 "**** selected " << nSemiHeavy_ << " Z events with only 1 selected parton." << std::endl <<
469 "=====================================================================" << std::endl <<
470 "**** Selected (Z) events composed of : " << nTotal_ << " quarks, " << std::endl <<
471 "**** --------------------------- " << nLight_ << " u,d,s " << std::endl <<
472 "**** --------------------------- " << nGluon_ << " gluon " << std::endl <<
473 "**** --------------------------- " << nCharm_ << " c " << std::endl <<
474 "**** --------------------------- " << nBottom_ << " b " << std::endl <<
475 "=====================================================================" << std::endl;
476
477 }
478
479
480
481 }//namespace
482
483