Skip to content

Commit de637b5

Browse files
author
Michele Mormile
committed
Included isolation and selected only photons from decay of hard process
1 parent c984d9c commit de637b5

File tree

2 files changed

+90
-17
lines changed

2 files changed

+90
-17
lines changed

GeneratorInterface/GenFilters/plugins/PhotonGenFilter.cc

Lines changed: 89 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "GeneratorInterface/GenFilters/plugins/PhotonGenFilter.h"
22
#include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
3-
#include "GeneratorInterface/GenFilters/plugins/MCFilterZboostHelper.h"
43
#include <iostream>
54

65
using namespace edm;
@@ -26,42 +25,83 @@ bool PhotonGenFilter::filter(edm::StreamID, edm::Event &iEvent, const edm::Event
2625
Handle<HepMCProduct> evt;
2726
iEvent.getByToken(token_, evt);
2827
const HepMC::GenEvent *myGenEvent = evt->GetEvent();
28+
bool accepted_event = false;
2929

3030
for (HepMC::GenEvent::particle_const_iterator p = myGenEvent->particles_begin(); p != myGenEvent->particles_end();
31-
++p) {
32-
if ((*p)->pdg_id() == 22) {
31+
++p) { // loop through all particles
32+
if ((*p)->pdg_id() == 22 && !hasAncestor(*p,[](int x){return x > 30 && x != 2212;})) { // loop through all photons that don't come from hadrons
3333
if ((*p)->momentum().perp() > ptMin && (*p)->status() == 1 && (*p)->momentum().eta() > etaMin &&
34-
(*p)->momentum().eta() < etaMax) {
35-
bool accepted_photon = true;
34+
(*p)->momentum().eta() < etaMax) { // check if photon passes pt and eta cuts
35+
bool good_photon = true;
3636
double phi = (*p)->momentum().phi();
3737
double eta = (*p)->momentum().eta();
38+
double pt = (*p)->momentum().perp();
39+
double frixione_isolation_coefficient = pt/(1-cos(drMin));
40+
vector<double> particles_pt, particles_deltar;
3841
for (HepMC::GenEvent::particle_const_iterator q = myGenEvent->particles_begin();
3942
q != myGenEvent->particles_end();
40-
++q) {
41-
if (&p != &q) {
42-
if ((*q)->momentum().perp() > ptThreshold && (*q)->pdg_id() != 22 &&
43-
(*q)->status() == 1) // && abs((*q)->charge()) > 0)
44-
{
45-
double phi2 = (*p)->momentum().phi();
43+
++q) { // loop through all particles to compute frixione isolation
44+
if (&p != &q) { // don't compare the photon to itself
45+
if ((*q)->momentum().perp() > ptThreshold && (*q)->pdg_id() != 22 && (*q)->pdg_id() != 12 &&
46+
(*q)->pdg_id() != 14 && (*q)->pdg_id() != 16 &&
47+
(*q)->status() == 1)
48+
{ // check if particle passes pt and status cuts and is not a neutrino or photon
49+
double phi2 = (*q)->momentum().phi();
4650
double deltaphi = fabs(phi - phi2);
4751
if (deltaphi > M_PI)
4852
deltaphi = 2. * M_PI - deltaphi;
49-
double eta2 = (*p)->momentum().eta();
53+
double eta2 = (*q)->momentum().eta();
5054
double deltaeta = fabs(eta - eta2);
5155
double deltaR = sqrt(deltaeta * deltaeta + deltaphi * deltaphi);
52-
if (deltaR < drMin)
53-
accepted_photon = false;
56+
if (deltaR < drMin) // check if particle is within drMin of photon, for isolation
57+
{
58+
particles_pt.push_back((*q)->momentum().perp());
59+
particles_deltar.push_back(deltaR);
60+
}
61+
}
62+
}
63+
}
64+
//order particles_pt and particles_deltar according to increasing particles_deltar
65+
for (unsigned int i = 0; i < particles_deltar.size(); i++)
66+
{
67+
for (unsigned int j = i + 1; j < particles_deltar.size(); j++)
68+
{
69+
if (particles_deltar[i] > particles_deltar[j])
70+
{
71+
double temp = particles_deltar[i];
72+
particles_deltar[i] = particles_deltar[j];
73+
particles_deltar[j] = temp;
74+
temp = particles_pt[i];
75+
particles_pt[i] = particles_pt[j];
76+
particles_pt[j] = temp;
5477
}
5578
}
5679
}
57-
if (accepted_photon)
58-
return true;
80+
//calculate frixione isolation
81+
double total_pt = 0;
82+
for (unsigned int i = 0; i < particles_deltar.size(); i++)
83+
{
84+
total_pt += particles_pt[i];
85+
if (total_pt > frixione_isolation_coefficient * (1 - cos(particles_deltar[i])))
86+
{
87+
good_photon = false; // if for some delta R the isolation condition is not satisfied, the photon is not good
88+
break;
89+
}
90+
}
91+
if (good_photon){
92+
if (hasAncestor(*p,[](int x){return x == 11 || x == 13 || x ==15;}) || hasAncestor(*p,[](int x){return x == 24 || x == 5;},true,false)) { // check if photon is from decay and defines the event as acceptable
93+
accepted_event = true;
94+
}
95+
if (!hasAncestor(*p,[](int x){return x == 11 || x == 13 || x ==15;}) && hasAncestor(*p,[](int x){return x == 24 || x == 5;},false,true)) { // check if photon comes from the hard process and discards it, in case it is
96+
return false;
97+
}
98+
}
5999
}
60100
}
61101
}
62102

63103
// Implementation for event filtering
64-
return false; // Return true if event passes the filter, false otherwise
104+
return accepted_event; // Accept if it has found at least one good photon from decay and none from hard process
65105
}
66106

67107
void PhotonGenFilter::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
@@ -75,4 +115,36 @@ void PhotonGenFilter::fillDescriptions(edm::ConfigurationDescriptions &descripti
75115
descriptions.add("PhotonGenFilter", desc);
76116
}
77117

118+
119+
bool PhotonGenFilter::hasAncestor(HepMC::GenParticle* particle, function<bool(int)> check,bool isWorBFromDecayCheck,bool isWorBPromptCheck) const { // function to check if a particle has a certain ancestor
120+
if (!particle) return false;
121+
122+
HepMC::GenVertex* prodVertex = particle->production_vertex();
123+
124+
// If the particle doesn't have a production vertex, it has no parents.
125+
if (!prodVertex) return false;
126+
127+
// Loop over all parents (incoming particles) of the vertex
128+
for (auto parent = prodVertex->particles_begin(HepMC::parents);
129+
parent != prodVertex->particles_end(HepMC::parents); ++parent) {
130+
131+
int pdgId = abs((*parent)->pdg_id());
132+
133+
// Check if the PDG ID respects a check
134+
if (check(pdgId)) {
135+
if (isWorBFromDecayCheck) {
136+
return hasAncestor(*parent,[](int x){return x == 6;},false,false); // if the photon has a W or b quark ancestor, check if it comes from a top quark
137+
}
138+
else if (isWorBPromptCheck) {
139+
return !hasAncestor(*parent,[](int x){return x == 6;},false,false); // if the photon has a W or b quark ancestor, check that it doesn't come from a top quark decay (therefore it comes form the hard process)
140+
}
141+
else return true;
142+
}
143+
144+
return hasAncestor(*parent, check,isWorBFromDecayCheck,isWorBPromptCheck); // Recursively check the ancestry of the parent
145+
}
146+
147+
return false;
148+
}
149+
78150
DEFINE_FWK_MODULE(PhotonGenFilter);

GeneratorInterface/GenFilters/plugins/PhotonGenFilter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class PhotonGenFilter : public edm::global::EDFilter<> {
2222
~PhotonGenFilter() override;
2323

2424
bool filter(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
25+
bool hasAncestor(HepMC::GenParticle* particle, std::function<bool(int)> check,bool isWorBFromDecayCheck=false,bool isWorBPromptCheck=false) const;
2526
static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
2627

2728
private:

0 commit comments

Comments
 (0)