CMS 3D CMS Logo

deltar.py
Go to the documentation of this file.
1 # Copyright (C) 2014 Colin Bernet
2 # https://github.com/cbernet/heppy/blob/master/LICENSE
3 
4 import math
5 import copy
6 
7 def deltaR2( e1, p1, e2=None, p2=None):
8  """Take either 4 arguments (eta,phi, eta,phi) or two objects that have 'eta', 'phi' methods)"""
9  if (e2 == None and p2 == None):
10  return deltaR2(e1.eta(),e1.phi(), p1.eta(), p1.phi())
11  de = e1 - e2
12  dp = deltaPhi(p1, p2)
13  return de*de + dp*dp
14 
15 
16 def deltaR( *args ):
17  return math.sqrt( deltaR2(*args) )
18 
19 
20 def deltaPhi( p1, p2):
21  '''Computes delta phi, handling periodic limit conditions.'''
22  res = p1 - p2
23  while res > math.pi:
24  res -= 2*math.pi
25  while res < -math.pi:
26  res += 2*math.pi
27  return res
28 
29 
30 def inConeCollection(pivot, particles, deltaRMax, deltaRMin=1e-5):
31  '''Returns the list of particles that are less than deltaRMax away from pivot.'''
32  dR2Max = deltaRMax ** 2
33  dR2Min = deltaRMin ** 2 if deltaRMin > 0 else -1
34  results = []
35  for ptc in particles:
36  dR2 = deltaR2(pivot.eta(), pivot.phi(), ptc.eta(), ptc.phi())
37  if dR2Min < dR2 and dR2 < dR2Max:
38  results.append(ptc)
39  return results
40 
41 def matchObjectCollection3 ( objects, matchCollection, deltaRMax = 0.3, filter = lambda x,y : True ):
42  '''Univoque association of an element from matchCollection to an element of objects.
43  Reco and Gen objects get the "matched" attribute, true is they are re part of a matched tulpe.
44  By default, the matching is true only if delta R is smaller than 0.3.
45  '''
46  #
47 
48  pairs = {}
49  if len(objects)==0:
50  return pairs
51  if len(matchCollection)==0:
52  return dict( list(zip(objects, [None]*len(objects))) )
53  # build all possible combinations
54 
55  objectCoords = [ (o.eta(),o.phi(),o) for o in objects ]
56  matchdCoords = [ (o.eta(),o.phi(),o) for o in matchCollection ]
57  allPairs = sorted([(deltaR2 (oeta, ophi, meta, mphi), (object, match)) for (oeta,ophi,object) in objectCoords for (meta,mphi,match) in matchdCoords if abs(oeta-meta)<=deltaRMax and filter(object,match) ])
58  #allPairs = [(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection if filter(object,match) ]
59  #
60  # to flag already matched objects
61  # FIXME this variable remains appended to the object, I do not like it
62 
63  for object in objects:
64  object.matched = False
65  for match in matchCollection:
66  match.matched = False
67  #
68 
69  deltaR2Max = deltaRMax * deltaRMax
70  for dR2, (object, match) in allPairs:
71  if dR2 > deltaR2Max:
72  break
73  if dR2 < deltaR2Max and object.matched == False and match.matched == False:
74  object.matched = True
75  match.matched = True
76  pairs[object] = match
77  #
78 
79  for object in objects:
80  if object.matched == False:
81  pairs[object] = None
82  #
83 
84  return pairs
85  # by now, the matched attribute remains in the objects, for future usage
86  # one could remove it with delattr (object, attrname)
87 
88 
89 
90 
91 def cleanObjectCollection2( objects, masks, deltaRMin ):
92  '''Masks objects using a deltaR cut, another algorithm (same results).'''
93  if len(objects)==0:
94  return objects
95  deltaR2Min = deltaRMin*deltaRMin
96  cleanObjects = copy.copy( objects )
97  for mask in masks:
98  tooClose = []
99  for idx, object in enumerate(cleanObjects):
100  dR2 = deltaR2( object.eta(), object.phi(),
101  mask.eta(), mask.phi() )
102  if dR2 < deltaR2Min:
103  tooClose.append( idx )
104  nRemoved = 0
105  for idx in tooClose:
106  # yes, everytime an object is removed, the list of objects is updated
107  # so need to update the index accordingly.
108  # example: to remove : ele 1 and 2
109  # first, ele 1 is removed
110  # -> ele 2 is now at index 1
111  # one should again remove the element at index 1
112  idx -= nRemoved
113  del cleanObjects[idx]
114  nRemoved += 1
115  return cleanObjects
116 
117 
118 def cleanObjectCollection( objects, masks, deltaRMin ):
119  '''Masks objects using a deltaR cut.'''
120  if len(objects)==0 or len(masks)==0:
121  return objects, []
122  deltaR2Min = deltaRMin*deltaRMin
123  cleanObjects = []
124  dirtyObjects = []
125  for object in objects:
126  ok = True
127  for mask in masks:
128  dR2 = deltaR2( object.eta(), object.phi(),
129  mask.eta(), mask.phi() )
130  if dR2 < deltaR2Min:
131  ok = False
132  if ok:
133  cleanObjects.append( object )
134  else:
135  dirtyObjects.append( object )
136  return cleanObjects, dirtyObjects
137 
138 def bestMatch( object, matchCollection):
139  '''Return the best match to object in matchCollection, which is the closest object in delta R'''
140  deltaR2Min = float('+inf')
141  bm = None
142  for match in matchCollection:
143  dR2 = deltaR2( object.eta(), object.phi(),
144  match.eta(), match.phi() )
145  if dR2 < deltaR2Min:
146  deltaR2Min = dR2
147  bm = match
148  return bm, deltaR2Min
149 
150 
151 def matchObjectCollection( objects, matchCollection, deltaR2Max, filter = lambda x,y : True):
152  pairs = {}
153  if len(objects)==0:
154  return pairs
155  if len(matchCollection)==0:
156  return dict( list(zip(objects, [None]*len(objects))) )
157  for object in objects:
158  bm, dr2 = bestMatch( object, [mob for mob in matchCollection if filter(object,mob)] )
159  if dr2<deltaR2Max:
160  pairs[object] = bm
161  else:
162  pairs[object] = None
163  return pairs
164 
165 
166 def matchObjectCollection2 ( objects, matchCollection, deltaRMax = 0.3 ):
167  '''Univoque association of an element from matchCollection to an element of objects.
168  Reco and Gen objects get the "matched" attribute, true is they are re part of a matched tulpe.
169  By default, the matching is true only if delta R is smaller than 0.3.
170  '''
171 
172  pairs = {}
173  if len(objects)==0:
174  return pairs
175  if len(matchCollection)==0:
176  return dict( list(zip(objects, [None]*len(objects))) )
177  # build all possible combinations
178  allPairs = sorted([(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection])
179 
180  # to flag already matched objects
181  # FIXME this variable remains appended to the object, I do not like it
182  for object in objects:
183  object.matched = False
184  for match in matchCollection:
185  match.matched = False
186 
187  deltaR2Max = deltaRMax * deltaRMax
188  for dR2, (object, match) in allPairs:
189  if dR2 > deltaR2Max:
190  break
191  if dR2 < deltaR2Max and object.matched == False and match.matched == False:
192  object.matched = True
193  match.matched = True
194  pairs[object] = match
195 
196  for object in objects:
197  if object.matched == False:
198  pairs[object] = None
199 
200  return pairs
201  # by now, the matched attribute remains in the objects, for future usage
202  # one could remove it with delattr (object, attrname)
203 
204 
205 
def deltaR(args)
Definition: deltar.py:16
def deltaR2(e1, p1, e2=None, p2=None)
Definition: deltar.py:7
def deltaPhi(p1, p2)
Definition: deltar.py:20
def matchObjectCollection
Definition: deltar.py:151
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
def bestMatch(object, matchCollection)
Definition: deltar.py:138
def cleanObjectCollection(objects, masks, deltaRMin)
Definition: deltar.py:118
def matchObjectCollection2(objects, matchCollection, deltaRMax=0.3)
Definition: deltar.py:166
def inConeCollection(pivot, particles, deltaRMax, deltaRMin=1e-5)
Definition: deltar.py:30
def matchObjectCollection3
Definition: deltar.py:41
def cleanObjectCollection2(objects, masks, deltaRMin)
Definition: deltar.py:91