CMS 3D CMS Logo

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