CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
doubleEMEnrichingFilterAlgo.cc
Go to the documentation of this file.
2 
4 
11 
14 
18 
19 #include "CLHEP/Vector/LorentzVector.h"
20 
21 
22 using namespace edm;
23 using namespace std;
24 
25 
27 
28  //set constants
29  FILTER_TKISOCUT_=2;
30  FILTER_CALOISOCUT_=2;
31  FILTER_ETA_MIN_=0;
32  FILTER_ETA_MAX_=2.5;
33  ECALBARRELMAXETA_=1.479;
34  ECALBARRELRADIUS_=129.0;
35  ECALENDCAPZ_=304.5;
36 
37  // from bctoe
38  eTThreshold_=(float)iConfig.getParameter<double>("eTThreshold");
39 
40  isoGenParETMin_=(float) iConfig.getParameter<double>("isoGenParETMin");
41  isoGenParConeSize_=(float) iConfig.getParameter<double>("isoGenParConeSize");
42  clusterThreshold_=(float) iConfig.getParameter<double>("clusterThreshold");
43  seedThreshold_=(float) iConfig.getParameter<double>("seedThreshold");
44  isoConeSize_=(float) iConfig.getParameter<double>("isoConeSize");
45  hOverEMax_=(float) iConfig.getParameter<double>("hOverEMax");
46  tkIsoMax_=(float) iConfig.getParameter<double>("tkIsoMax");
47  caloIsoMax_=(float) iConfig.getParameter<double>("caloIsoMax");
48  requireTrackMatch_=iConfig.getParameter<bool>("requireTrackMatch");
49  genParSource_=iConfig.getParameter<edm::InputTag>("genParSource");
50 
51 }
52 
54 }
55 
56 
58 
59 
60  //----------
61 
63  iEvent.getByLabel(genParSource_,genParsHandle);
64  reco::GenParticleCollection genPars=*genParsHandle;
65 
66  bool result = false;
67  int BCtoEgood=0;
68  int PhotElecgood=0;
69  int IsoGenPargood=0;
70 
71  // cleaning
72  sel1seeds.clear();
73  sel2seeds.clear();
74  selBCtoEseeds.clear();
75 
76  //bending of traj. of charged particles under influence of B-field
77  std::vector<reco::GenParticle> genParsCurved=applyBFieldCurv(genPars,iSetup);
78 
79  PhotElecgood=filterPhotonElectronSeed(clusterThreshold_,
80  seedThreshold_,
81  isoConeSize_,
82  hOverEMax_,
83  tkIsoMax_,
84  caloIsoMax_,
85  requireTrackMatch_,
86  genPars,
87  genParsCurved);
88 
89  IsoGenPargood=filterIsoGenPar(isoGenParETMin_,isoGenParConeSize_,genPars,genParsCurved);
90 
91 
93  for (uint32_t ig=0;ig<genParsCurved.size();ig++) {
94  reco::GenParticle gp=genParsCurved.at(ig);
95  if (gp.status()==1 && abs(gp.pdgId())==11 && gp.et()>eTThreshold_ && fabs(gp.eta())<FILTER_ETA_MAX_) {
96  if (hasBCAncestors(gp)) {
97  BCtoEgood++;
98  selBCtoEseeds.push_back(gp);
99  }
100  }
101  }
102 
103  // we want 2 different em candidates
104  if ( PhotElecgood> 1) {
105  result = true;
106  }
107  else if ( IsoGenPargood> 1) {
108  result = true;
109  }
110  else if ( BCtoEgood > 1) {
111  result = true;
112  }
113  else if ( PhotElecgood==1 && IsoGenPargood==1) {
114  if ( (sel1seeds.at(0).eta()!=sel2seeds.at(0).eta()) && (sel1seeds.at(0).phi()!=sel2seeds.at(0).phi()) && (sel1seeds.at(0).et()!=sel2seeds.at(0).et()) ) result = true;
115  }
116  else if ( PhotElecgood==1 && BCtoEgood==1) {
117  if ( (sel1seeds.at(0).eta()!=selBCtoEseeds.at(0).eta()) && (sel1seeds.at(0).phi()!=selBCtoEseeds.at(0).phi()) && (sel1seeds.at(0).et()!=selBCtoEseeds.at(0).et()) ) result = true;
118  }
119  else if ( BCtoEgood==1 && IsoGenPargood==1) {
120  if ( (selBCtoEseeds.at(0).eta()!=sel2seeds.at(0).eta()) && (selBCtoEseeds.at(0).phi()!=sel2seeds.at(0).phi()) && (selBCtoEseeds.at(0).et()!=sel2seeds.at(0).et()) ) result = true;
121  }
122 
123  return result;
124 
125 }
126 
127 
128 
129 //filter that uses clustering around photon and electron seeds
130 //only electrons, photons, charged pions, and charged kaons are clustered
131 //additional requirements:
132 
133 
134 //seed threshold, total threshold, and cone size/shape are specified separately for the barrel and the endcap
136  float seedthreshold,
137  float isoConeSize,
138  float hOverEMax,
139  float tkIsoMax,
140  float caloIsoMax,
141  bool requiretrackmatch,
142  const std::vector<reco::GenParticle> &genPars,
143  const std::vector<reco::GenParticle> &genParsCurved) {
144 
145  float conesizeendcap=15;
146 
147  int retval=0;
148 
149  vector<reco::GenParticle> seeds;
150  //find electron and photon seeds - must have E>seedthreshold GeV
151  for (uint32_t is=0;is<genParsCurved.size();is++) {
152  reco::GenParticle gp=genParsCurved.at(is);
153  if (gp.status()!=1 || fabs(gp.eta()) > FILTER_ETA_MAX_ || fabs(gp.eta()) < FILTER_ETA_MIN_) continue;
154  int absid=abs(gp.pdgId());
155  if (absid!=11 && absid!=22) continue;
156  if (gp.et()>seedthreshold) seeds.push_back(gp);
157  }
158 
159  bool matchtrack=false;
160 
161  //for every seed, try to cluster stable particles about it in cone
162  for (uint32_t is=0;is<seeds.size();is++) {
163  float eTInCone=0;//eT associated to the electron cluster
164  float tkIsoET=0;//tracker isolation energy
165  float caloIsoET=0;//calorimeter isolation energy
166  float hadET=0;//isolation energy from heavy hadrons that goes in the same area as the "electron" - so contributes to H/E
167  bool isBarrel=fabs(seeds.at(is).eta())<ECALBARRELMAXETA_;
168  for (uint32_t ig=0;ig<genParsCurved.size();ig++) {
169  reco::GenParticle gp=genParsCurved.at(ig);
170  reco::GenParticle gpUnCurv=genPars.at(ig);//for tk isolation, p at vertex
171  if (gp.status()!=1) continue;
172  int gpabsid=abs(gp.pdgId());
173  if (gp.et()<1) continue;//ignore very soft particles
174  //BARREL
175  if (isBarrel) {
176  float dr=deltaR(seeds.at(is),gp);
177  float dphi=deltaPhi(seeds.at(is).phi(),gp.phi());
178  float deta=fabs(seeds.at(is).eta()-gp.eta());
179  if (deta<0.03 && dphi<0.2) {
180  if (gpabsid==22 || gpabsid==11 || gpabsid==211 || gpabsid==321) {
181  //contributes to electron
182  eTInCone+=gp.et();
183  //check for a matched track with at least 5 GeV
184  if ((gpabsid==11 || gpabsid==211 || gpabsid==321) && gp.et()>5) matchtrack=true;
185  } else {
186  //contributes to H/E
187  hadET+=gp.et();
188  }
189  } else {
190  float drUnCurv=deltaR(seeds.at(is),gpUnCurv);
191  if ((gp.charge()==0 && dr<isoConeSize && gpabsid!=22) ||
192  (gp.charge()!=0 && drUnCurv<isoConeSize)) {
193  //contributes to calo isolation energy
194  caloIsoET+=gp.et();
195  }
196  if (gp.charge()!=0 && drUnCurv<isoConeSize) {
197  //contributes to track isolation energy
198  tkIsoET+=gp.et();
199  }
200  }
201  //ENDCAP
202  } else {
203  float drxy=deltaRxyAtEE(seeds.at(is),gp);
204  float dr=deltaR(seeds.at(is),gp);//the isolation is done in dR
205  if (drxy<conesizeendcap) {
206  if (gpabsid==22 || gpabsid==11 || gpabsid==211 || gpabsid==321) {
207  //contributes to electron
208  eTInCone+=gp.et();
209  //check for a matched track with at least 5 GeV
210  if ((gpabsid==11 || gpabsid==211 || gpabsid==321) && gp.et()>5) matchtrack=true;
211  } else {
212  //contributes to H/E
213  hadET+=gp.et();
214  }
215  } else {
216  float drUnCurv=deltaR(seeds.at(is),gpUnCurv);
217  if ((gp.charge()==0 && dr<isoConeSize && gpabsid!=22) ||
218  (gp.charge()!=0 && drUnCurv<isoConeSize)) {
219  //contributes to calo isolation energy
220  caloIsoET+=gp.et();
221  }
222  if (gp.charge()!=0 && drUnCurv<isoConeSize) {
223  //contributes to track isolation energy
224  tkIsoET+=gp.et();
225  }
226  }
227  }
228  }
229 
230  if (eTInCone>clusterthreshold && (!requiretrackmatch || matchtrack)) {
231  // cout <<"isoET: "<<isoET<<endl;
232  if (hadET/eTInCone<hOverEMax && tkIsoET<tkIsoMax && caloIsoET<caloIsoMax) {
233  retval=retval+1;
234  sel1seeds.push_back(seeds[is]);
235  // break;
236  }
237  }
238  }
239 
240  return retval;
241 }
242 
243 
244 
245 
246 //make new genparticles vector taking into account the bending of charged particles in the b field
247 //only stable-final-state (status==1) particles, with ET>=1 GeV, have their trajectories bent
248 std::vector<reco::GenParticle> doubleEMEnrichingFilterAlgo::applyBFieldCurv(const std::vector<reco::GenParticle> &genPars, const edm::EventSetup& iSetup) {
249 
250 
251  vector<reco::GenParticle> curvedPars;
252 
254  iSetup.get<IdealMagneticFieldRecord>().get(magField);
255 
259 
261 
262  for (uint32_t ig=0;ig<genPars.size();ig++) {
263  reco::GenParticle gp=genPars.at(ig);
264  //don't bend trajectories of neutral particles, unstable particles, particles with < 1 GeV
265  //particles with < ~0.9 GeV don't reach the barrel
266  //so just put them as-is into the new vector
267  if (gp.charge()==0 || gp.status()!=1 || gp.et()<1) {
268  curvedPars.push_back(gp);
269  continue;
270  }
271  GlobalPoint vertex(gp.vx(),gp.vy(),gp.vz());
272  GlobalVector gvect(gp.px(),gp.py(),gp.pz());
273  FreeTrajectoryState fts(vertex,gvect,gp.charge(),&(*magField));
275  //choose to propagate to barrel, +Z endcap, or -Z endcap, according to eta
276  if (fabs(gp.eta())<ECALBARRELMAXETA_) {
277  impact=propagator.propagate(fts,*theBarrel);
278  } else if (gp.eta()>0) {
279  impact=propagator.propagate(fts,*endCapPlus);
280  } else {
281  impact=propagator.propagate(fts,*endCapMinus);
282  }
283  //in case the particle doesn't reach the barrel/endcap, just put it as-is into the new vector
284  //it should reach though.
285  if (!impact.isValid()) {
286  curvedPars.push_back(gp);
287  continue;
288  }
290 
291  //the magnitude of p doesn't change, only the direction
292  //NB I do get some small change in magnitude by the following,
293  //I think it is a numerical precision issue
294  float et=gp.et();
295  float phinew=impact.globalPosition().phi();
296  float pxnew=et*cos(phinew);
297  float pynew=et*sin(phinew);
298  newp4.SetPx(pxnew);
299  newp4.SetPy(pynew);
300  newp4.SetPz(gp.pz());
301  newp4.SetE(gp.energy());
302  reco::GenParticle gpnew=gp;
303  gpnew.setP4(newp4);
304  curvedPars.push_back(gpnew);
305  }
306  return curvedPars;
307 
308 
309 }
310 
311 //calculate the difference in the xy-plane positions of gp1 and gp1 at the ECAL endcap
312 //if they go in different z directions returns 9999.
314 
315  if (gp1.pz()*gp2.pz() < 0) return 9999.;
316 
317  float rxy1=ECALENDCAPZ_*tan(gp1.theta());
318  float x1=cos(gp1.phi())*rxy1;
319  float y1=sin(gp1.phi())*rxy1;
320 
321  float rxy2=ECALENDCAPZ_*tan(gp2.theta());
322  float x2=cos(gp2.phi())*rxy2;
323  float y2=sin(gp2.phi())*rxy2;
324 
325  float dxy=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
326  return dxy;
327 
328 
329 }
330 
331 
332 //filter looking for isolated charged pions, charged kaons, and electrons.
333 //isolation done in cone of given size, looking at charged particles and neutral hadrons
334 //photons aren't counted in the isolation requirements
335 
336 //need to have both the the curved and uncurved genpar collections
337 //because tracker iso has to be treated differently than calo iso
339  const reco::GenParticleCollection &gphCurved
340  ) {
341 
342  int passed = 0;
343  for (uint32_t ip=0;ip<gph.size();ip++) {
344 
345  reco::GenParticle gp=gph.at(ip);
346  reco::GenParticle gpCurved=gphCurved.at(ip);
347  int gpabsid=abs(gp.pdgId());
348  //find potential candidates
349  if (gp.et()<=etmin || gp.status()!=1) continue;
350  if (gpabsid!=11 && gpabsid != 211 && gpabsid!= 321) continue;
351  if (fabs(gp.eta()) < FILTER_ETA_MIN_) continue;
352  if (fabs(gp.eta()) > FILTER_ETA_MAX_) continue;
353 
354  //check isolation
355  float tkiso=0;
356  float caloiso=0;
357  for (uint32_t jp=0;jp<gph.size();jp++) {
358  if (jp==ip) continue;
359  reco::GenParticle pp=gph.at(jp);
360  reco::GenParticle ppCurved=gphCurved.at(jp);
361  if (pp.status() != 1) continue;
362  float dr=deltaR(gp,pp);
363  float drCurved=deltaR(gpCurved,ppCurved);
364  if (abs(pp.charge())==1 && pp.et()>2 && dr<conesize) {
365  tkiso+=pp.et();
366  }
367  if (pp.et()>2 && abs(pp.pdgId())!=22 && drCurved<conesize) {
368  caloiso+=pp.energy();
369  }
370  }
371  if (tkiso<FILTER_TKISOCUT_ && caloiso<FILTER_CALOISOCUT_) {
372  sel2seeds.push_back(gpCurved);
373  passed++;
374  }
375  }
376  return passed;
377 }
378 
379 //does this particle have an ancestor (mother, mother of mother, etc.) that is a b or c hadron?
380 //attention: the GenParticle argument must have the motherRef correctly filled for this
381 //to work. That is, you had better have got it out of the genParticles collection
383 
384  //stopping condition: this particle is a b or c hadron
385  if (isBCHadron(gp)) return true;
386  //stopping condition: this particle has no mothers
387  if (gp.numberOfMothers()==0) return false;
388  //otherwise continue
389  bool retval=false;
390  for (uint32_t im=0;im<gp.numberOfMothers();im++) {
391  retval=retval || hasBCAncestors(*gp.motherRef(im));
392  }
393  return retval;
394 
395 }
396 
398  return isBCMeson(gp) || isBCBaryon(gp);
399 }
400 
402 
403  uint32_t pdgid=abs(gp.pdgId());
404  uint32_t hundreds=pdgid%1000;
405  if (hundreds>=400 && hundreds<600) {
406  return true;
407  } else {
408  return false;
409  }
410 
411 }
412 
414 
415  uint32_t pdgid=abs(gp.pdgId());
416  uint32_t thousands=pdgid%10000;
417  if (thousands>=4000 && thousands <6000) {
418  return true;
419  } else {
420  return false;
421  }
422 
423 }
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
T getParameter(std::string const &) const
virtual int pdgId() const
PDG identifier.
int filterIsoGenPar(float etmin, float conesize, const reco::GenParticleCollection &gph, const reco::GenParticleCollection &gphCurved)
tuple pp
Definition: createTree.py:15
virtual double et() const
transverse energy
virtual int status() const
status word
bool isBarrel(GeomDetEnumerators::SubDetector m)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
virtual void setP4(const LorentzVector &p4)
set 4-momentum
virtual double vy() const
y coordinate of vertex position
virtual double eta() const
momentum pseudorapidity
bool isBCBaryon(const reco::GenParticle &gp)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
static CylinderPointer build(const PositionType &pos, const RotationType &rot, Scalar radius, Bounds *bounds=0)
Definition: Cylinder.h:51
virtual double energy() const
energy
int iEvent
Definition: GenABIO.cc:230
virtual size_t numberOfMothers() const
number of mothers
T sqrt(T t)
Definition: SSEVec.h:48
bool isBCMeson(const reco::GenParticle &gp)
tuple result
Definition: query.py:137
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
bool isBCHadron(const reco::GenParticle &gp)
virtual int charge() const
electric charge
Definition: LeafCandidate.h:91
bool hasBCAncestors(const reco::GenParticle &gp)
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< reco::GenParticle > applyBFieldCurv(const std::vector< reco::GenParticle > &genPars, const edm::EventSetup &iSetup)
virtual double vz() const
z coordinate of vertex position
daughters::value_type motherRef(size_type i=0) const
reference to mother at given position
bool getByLabel(InputTag const &tag, Handle< PROD > &result) const
Definition: Event.h:420
virtual double theta() const
momentum polar angle
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
int filterPhotonElectronSeed(float clusterthreshold, float seedthreshold, float isoConeSize, float hOverEMax, float tkIsoMax, float caloIsoMax, bool requiretrackmatch, const std::vector< reco::GenParticle > &genPars, const std::vector< reco::GenParticle > &genParsCurved)
virtual double px() const
x coordinate of momentum vector
const T & get() const
Definition: EventSetup.h:56
virtual double pz() const
z coordinate of momentum vector
float deltaRxyAtEE(const reco::GenParticle &gp1, const reco::GenParticle &gp2)
virtual double vx() const
x coordinate of vertex position
bool filter(const edm::Event &iEvent, const edm::EventSetup &iSetup)
virtual double phi() const
momentum azimuthal angle
doubleEMEnrichingFilterAlgo(const edm::ParameterSet &)
virtual double py() const
y coordinate of momentum vector