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=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
34  results = []
35  for ptc in particles:
36  dR2 = deltaR2(pivot.eta(), pivot.phi(), ptc.eta(), ptc.phi())
37  if dR2Min < 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 = [(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  allPairs.sort ()
60  #
61  # to flag already matched objects
62  # FIXME this variable remains appended to the object, I do not like it
63 
64  for object in objects:
65  object.matched = False
66  for match in matchCollection:
67  match.matched = False
68  #
69 
70  deltaR2Max = deltaRMax * deltaRMax
71  for dR2, (object, match) in allPairs:
72  if dR2 > deltaR2Max:
73  break
74  if dR2 < deltaR2Max and object.matched == False and match.matched == False:
75  object.matched = True
76  match.matched = True
77  pairs[object] = match
78  #
79 
80  for object in objects:
81  if object.matched == False:
82  pairs[object] = None
83  #
84 
85  return pairs
86  # by now, the matched attribute remains in the objects, for future usage
87  # one could remove it with delattr (object, attrname)
88 
89 
90 
91 
92 def cleanObjectCollection2( objects, masks, deltaRMin ):
93  '''Masks objects using a deltaR cut, another algorithm (same results).'''
94  if len(objects)==0:
95  return objects
96  deltaR2Min = deltaRMin*deltaRMin
97  cleanObjects = copy.copy( objects )
98  for mask in masks:
99  tooClose = []
100  for idx, object in enumerate(cleanObjects):
101  dR2 = deltaR2( object.eta(), object.phi(),
102  mask.eta(), mask.phi() )
103  if dR2 < deltaR2Min:
104  tooClose.append( idx )
105  nRemoved = 0
106  for idx in tooClose:
107  # yes, everytime an object is removed, the list of objects is updated
108  # so need to update the index accordingly.
109  # example: to remove : ele 1 and 2
110  # first, ele 1 is removed
111  # -> ele 2 is now at index 1
112  # one should again remove the element at index 1
113  idx -= nRemoved
114  del cleanObjects[idx]
115  nRemoved += 1
116  return cleanObjects
117 
118 
119 def cleanObjectCollection( objects, masks, deltaRMin ):
120  '''Masks objects using a deltaR cut.'''
121  if len(objects)==0 or len(masks)==0:
122  return objects, []
123  deltaR2Min = deltaRMin*deltaRMin
124  cleanObjects = []
125  dirtyObjects = []
126  for object in objects:
127  ok = True
128  for mask in masks:
129  dR2 = deltaR2( object.eta(), object.phi(),
130  mask.eta(), mask.phi() )
131  if dR2 < deltaR2Min:
132  ok = False
133  if ok:
134  cleanObjects.append( object )
135  else:
136  dirtyObjects.append( object )
137  return cleanObjects, dirtyObjects
138 
139 def bestMatch( object, matchCollection):
140  '''Return the best match to object in matchCollection, which is the closest object in delta R'''
141  deltaR2Min = float('+inf')
142  bm = None
143  for match in matchCollection:
144  dR2 = deltaR2( object.eta(), object.phi(),
145  match.eta(), match.phi() )
146  if dR2 < deltaR2Min:
147  deltaR2Min = dR2
148  bm = match
149  return bm, deltaR2Min
150 
151 
152 def matchObjectCollection( objects, matchCollection, deltaR2Max, filter = lambda x,y : True):
153  pairs = {}
154  if len(objects)==0:
155  return pairs
156  if len(matchCollection)==0:
157  return dict( list(zip(objects, [None]*len(objects))) )
158  for object in objects:
159  bm, dr2 = bestMatch( object, [mob for mob in matchCollection if filter(object,mob)] )
160  if dr2<deltaR2Max:
161  pairs[object] = bm
162  else:
163  pairs[object] = None
164  return pairs
165 
166 
167 def matchObjectCollection2 ( objects, matchCollection, deltaRMax = 0.3 ):
168  '''Univoque association of an element from matchCollection to an element of objects.
169  Reco and Gen objects get the "matched" attribute, true is they are re part of a matched tulpe.
170  By default, the matching is true only if delta R is smaller than 0.3.
171  '''
172 
173  pairs = {}
174  if len(objects)==0:
175  return pairs
176  if len(matchCollection)==0:
177  return dict( list(zip(objects, [None]*len(objects))) )
178  # build all possible combinations
179  allPairs = [(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection]
180  allPairs.sort ()
181 
182  # to flag already matched objects
183  # FIXME this variable remains appended to the object, I do not like it
184  for object in objects:
185  object.matched = False
186  for match in matchCollection:
187  match.matched = False
188 
189  deltaR2Max = deltaRMax * deltaRMax
190  for dR2, (object, match) in allPairs:
191  if dR2 > deltaR2Max:
192  break
193  if dR2 < deltaR2Max and object.matched == False and match.matched == False:
194  object.matched = True
195  match.matched = True
196  pairs[object] = match
197 
198  for object in objects:
199  if object.matched == False:
200  pairs[object] = None
201 
202  return pairs
203  # by now, the matched attribute remains in the objects, for future usage
204  # one could remove it with delattr (object, attrname)
205 
206 
207 
def bestMatch
Definition: deltar.py:139
def cleanObjectCollection
Definition: deltar.py:119
def deltaPhi
Definition: deltar.py:20
def matchObjectCollection
Definition: deltar.py:152
def cleanObjectCollection2
Definition: deltar.py:92
def matchObjectCollection2
Definition: deltar.py:167
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
def inConeCollection
Definition: deltar.py:30
def deltaR2
Definition: deltar.py:7
def deltaR
Definition: deltar.py:16
def matchObjectCollection3
Definition: deltar.py:41
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run