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 cleanObjectCollection2( objects, masks, deltaRMin ):
39  '''Masks objects using a deltaR cut, another algorithm (same results).'''
40  if len(objects)==0:
41  return objects
42  deltaR2Min = deltaRMin*deltaRMin
43  cleanObjects = copy.copy( objects )
44  for mask in masks:
45  tooClose = []
46  for idx, object in enumerate(cleanObjects):
47  dR2 = deltaR2( object.eta(), object.phi(),
48  mask.eta(), mask.phi() )
49  if dR2 < deltaR2Min:
50  tooClose.append( idx )
51  nRemoved = 0
52  for idx in tooClose:
53  # yes, everytime an object is removed, the list of objects is updated
54  # so need to update the index accordingly.
55  # example: to remove : ele 1 and 2
56  # first, ele 1 is removed
57  # -> ele 2 is now at index 1
58  # one should again remove the element at index 1
59  idx -= nRemoved
60  del cleanObjects[idx]
61  nRemoved += 1
62  return cleanObjects
63 
64 
65 def cleanObjectCollection( objects, masks, deltaRMin ):
66  '''Masks objects using a deltaR cut.'''
67  if len(objects)==0 or len(masks)==0:
68  return objects, []
69  deltaR2Min = deltaRMin*deltaRMin
70  cleanObjects = []
71  dirtyObjects = []
72  for object in objects:
73  ok = True
74  for mask in masks:
75  dR2 = deltaR2( object.eta(), object.phi(),
76  mask.eta(), mask.phi() )
77  if dR2 < deltaR2Min:
78  ok = False
79  if ok:
80  cleanObjects.append( object )
81  else:
82  dirtyObjects.append( object )
83  return cleanObjects, dirtyObjects
84 
85 def bestMatch( object, matchCollection):
86  '''Return the best match to object in matchCollection, which is the closest object in delta R'''
87  deltaR2Min = float('+inf')
88  bm = None
89  for match in matchCollection:
90  dR2 = deltaR2( object.eta(), object.phi(),
91  match.eta(), match.phi() )
92  if dR2 < deltaR2Min:
93  deltaR2Min = dR2
94  bm = match
95  return bm, deltaR2Min
96 
97 
98 def matchObjectCollection( objects, matchCollection, deltaR2Max):
99  pairs = {}
100  if len(objects)==0:
101  return pairs
102  if len(matchCollection)==0:
103  return dict( zip(objects, [None]*len(objects)) )
104  for object in objects:
105  bm, dr2 = bestMatch( object, matchCollection )
106  if dr2<deltaR2Max:
107  pairs[object] = bm
108  else:
109  pairs[object] = None
110  return pairs
111 
112 
113 def matchObjectCollection2 ( objects, matchCollection, deltaRMax = 0.3 ):
114  '''Univoque association of an element from matchCollection to an element of objects.
115  Reco and Gen objects get the "matched" attribute, true is they are re part of a matched tulpe.
116  By default, the matching is true only if delta R is smaller than 0.3.
117  '''
118 
119  pairs = {}
120  if len(objects)==0:
121  return pairs
122  if len(matchCollection)==0:
123  return dict( zip(objects, [None]*len(objects)) )
124  # build all possible combinations
125  allPairs = [(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection]
126  allPairs.sort ()
127 
128  # to flag already matched objects
129  # FIXME this variable remains appended to the object, I do not like it
130  for object in objects:
131  object.matched = False
132  for match in matchCollection:
133  match.matched = False
134 
135  deltaR2Max = deltaRMax * deltaRMax
136  for dR2, (object, match) in allPairs:
137  if dR2 > deltaR2Max:
138  break
139  if dR2 < deltaR2Max and object.matched == False and match.matched == False:
140  object.matched = True
141  match.matched = True
142  pairs[object] = match
143 
144  for object in objects:
145  if object.matched == False:
146  pairs[object] = None
147 
148  return pairs
149  # by now, the matched attribute remains in the objects, for future usage
150  # one could remove it with delattr (object, attrname)
151 
152 
153 
154 if __name__ == '__main__':
155 
156  import sys
157  args = sys.argv[1:]
158  fargs = map( float, args )
159 
160  print 'dR2 = ', deltaR2( *fargs )
161  print 'dR = ', deltaR( *fargs )
162 
163 
164 
def bestMatch
Definition: deltar.py:85
def cleanObjectCollection
Definition: deltar.py:65
def deltaPhi
Definition: deltar.py:17
tuple zip
Definition: archive.py:476
def matchObjectCollection
Definition: deltar.py:98
def cleanObjectCollection2
Definition: deltar.py:38
def matchObjectCollection2
Definition: deltar.py:113
def inConeCollection
Definition: deltar.py:27
def deltaR2
Definition: deltar.py:7
def deltaR
Definition: deltar.py:13