CMS 3D CMS Logo

ntuplePrintersDiff.py
Go to the documentation of this file.
1 from builtins import range
2 import re
3 import sys
4 import math
5 import difflib
6 import itertools
7 import collections
8 
9 from operator import itemgetter, methodcaller
10 
12 import six
13 
14 # Common track-track matching by hits (=clusters)
15 def _commonHits(trk1, trk2):
16  """Returns the number of common hits in trk1 and trk2. Matching is
17  done via the hit type and index, so effectively the matching is
18  done by clusters. Invalid hits are ignored.
19 
20  """
21  hits1 = set()
22  for hit in trk1.hits():
23  if not hit.isValidHit(): continue
24  hits1.add( (type(hit), hit.index()) )
25 
26  ncommon = 0
27  for hit in trk2.hits():
28  if not hit.isValidHit(): continue
29  if (type(hit), hit.index()) in hits1:
30  ncommon += 1
31 
32  return ncommon
33 
34 def _matchTracksByHits(reftrk, trklist):
35  if len(trklist) == 0:
36  return (None, 0)
37 
38  hits1 = set()
39  for hit in reftrk.hits():
40  if not hit.isValidHit(): continue
41  hits1.add( (type(hit), hit.index()) )
42 
43  best = (None, 0)
44  for trk in trklist:
45  ncommon = 0
46  for hit in trk.hits():
47  if not hit.isValidHit(): continue
48  if (type(hit), hit.index()) in hits1:
49  ncommon += 1
50  if ncommon > best[1]:
51  best = (trk, ncommon)
52 
53  return best
54 
56  def __init__(self, trklist):
57  super(_TracksByHitsMatcher, self).__init__()
58  self._hitsToTracks = collections.defaultdict(list)
59  for trk in trklist:
60  for hit in trk.hits():
61  if hit.isValidHit():
62  self._hitsToTracks[ (type(hit), hit.index()) ].append(trk)
63 
64  def match(self, trk):
65  tracks = collections.defaultdict(int)
66 
67  for hit in trk.hits():
68  if not hit.isValidHit(): continue
69 
70  idx = (type(hit), hit.index())
71  try:
72  otherTracks = self._hitsToTracks[idx]
73  except KeyError:
74  continue
75 
76  for ot in otherTracks:
77  tracks[ot] += 1
78 
79  best = (None, 0)
80  for t, ncommon in six.iteritems(tracks):
81  if ncommon > best[1]:
82  best = (t, ncommon)
83  return best
84 
85 
86 # Common diff helpers, used in the printout helpers
88  def __init__(self, diff=[], hasDifference=False):
89  self._diff = []
90  self._hasDifference = hasDifference
91  self.extend(diff)
92 
93  def setDifference(self, diff=True):
94  self._hasDifference = diff
95 
96  def hasDifference(self):
97  return self._hasDifference
98 
99  def extend(self, diff):
100  if isinstance(diff, _DiffResult):
101  self._diff.append(diff)
102  if diff.hasDifference():
103  self.setDifference()
104  else:
105  self._diff.extend(diff)
106 
107  def _highlightLine(self, line, plus, minus):
108  char = " "
109  if line[0] == "+":
110  if plus: char = "+"
111  elif line[0] == "-":
112  if minus: char = "-"
113  elif line[0] == "?":
114  char = "?"
115  return line[0]+char+line[1:]
116 
117  def highlight(self, plus=False, minus=False):
118  if not (plus or minus):
119  return
120 
121  for i, line in enumerate(self._diff):
122  if isinstance(line, _DiffResult):
123  line.highlight(plus, minus)
124  else:
125  self._diff[i] = self._highlightLine(line, plus, minus)
126 
127  def highlightLines(self, plusregexs=[], minusregexs=[]):
128  if len(plusregexs) == 0 and len(minusregexs) == 0:
129  return
130 
131  for i, line in enumerate(self._diff):
132  if isinstance(line, _DiffResult):
133  raise Exception("highlightLines() is currently allowed only for text-only _DiffResult objects")
134  plus = False
135  minus = False
136  for p in plusregexs:
137  if p.search(line):
138  plus = True
139  break
140  for m in minusregexs:
141  if m.search(line):
142  plus = True
143  break
144  self._diff[i] = self._highlightLine(line, plus, minus)
145 
146  def lines(self):
147  for line in self._diff:
148  if isinstance(line, _DiffResult):
149  for l in line.lines():
150  yield l
151  else:
152  yield line
153 
154  def __str__(self):
155  return "\n".join([s for s in (str(item) for item in self._diff) if s != ""])
156 
157  def __len__(self):
158  return len(self._diff)
159 
160 def _difflist(list1, list2):
161  diff = difflib.unified_diff(list1, list2, lineterm="", n=len(list1))
162  for item in diff:
163  if item[:2] == "@@":
164  break
165  return list(diff)
166 
167 def _makediff(list1, list2, equalPrefix=" "):
168  diff = _difflist(list1, list2)
169  if len(diff) == 0:
170  return _DiffResult([equalPrefix+s for s in list1], hasDifference=False)
171  else:
172  return _DiffResult(diff, hasDifference=True)
173 
174 def _mapdiff(func, obj1, obj2):
175  lst1 = func(obj1) if obj1 is not None else []
176  lst2 = func(obj2) if obj2 is not None else []
177  return _makediff(lst1, lst2)
178 
179 def _areSameTracks(trk1, trk2):
180  ncommon = _commonHits(trk1, trk2)
181 
182  # if tracks have same hits, consider their reco as identical
183  if not (ncommon == trk1.nValid() and ncommon == trk2.nValid()):
184  return False
185 
186  # although if there is any change in their iterations, mark them different
187  if not (trk1.algoMask() == trk2.algoMask() and trk1.algo() == trk2.algo() and trk1.originalAlgo() == trk2.originalAlgo()):
188  return False
189 
190  # if reco is the same, check if they are matched to the
191  # same TPs (in case the track-TP matching is modified
192  # between ntuples)
193  if trk1.nMatchedTrackingParticles() != trk2.nMatchedTrackingParticles():
194  return False
195 
196  for tpInfo1, tpInfo2 in itertools.izip(trk1.matchedTrackingParticleInfos(), trk2.matchedTrackingParticleInfos()):
197  if tpInfo1.trackingParticle().index() != tpInfo2.trackingParticle().index():
198  return False
199 
200  return True
201 
202 def diffTrackListsFromSameTrackingParticle(trackPrinter, lst1, lst2, lst1extra=[], lst2extra=[], diffByHitsOnly=False):
203  """lst1 and lst2 are the main lists to make the diff from.
204 
205  lst1extra and lst2extra are optional to provide suplementary
206  tracks. Use case: lst1 and lst2 are subset of full tracks,
207  lst1extra and lst2extra contain tracks matched to the same
208  TrackingParticle but are outside of the selection of lst1/lst2.
209  """
210 
211  diff = _DiffResult()
212 
213  _trks1extra = list(lst1extra)
214  _trks2extra = list(lst2extra)
215 
216  trks1 = list(lst1)+_trks1extra
217  trks2 = list(lst2)+_trks2extra # make copy because it is modified
218 
219  trks1extra = set([t.index() for t in _trks1extra])
220  trks2extra = set([t.index() for t in _trks2extra])
221 
222  trks1Empty = (len(trks1) == 0)
223  trks2Empty = (len(trks2) == 0)
224 
225  if trks1Empty and trks2Empty:
226  return diff
227 
228  # make sure all tracks really come from a single TP
229  # just to simplify the work loop, generalization can be considered later
230  commonTP = None
231  def _findCommonTP(_lst, _commonTP, _name):
232  for trk in _lst:
233  if trk.nMatchedTrackingParticles() != 1:
234  raise Exception("Track %d from %s is matched to %d TPs. This is not supported by this function yet." % (trk.index(), _name, trk.nMatchedTrackingParticles()))
235  if _commonTP is None:
236  _commonTP = next(trk.matchedTrackingParticleInfos()).trackingParticle()
237  else:
238  tp = next(trk.matchedTrackingParticleInfos()).trackingParticle()
239  if tp.index() != _commonTP.index():
240  raise Exception("Track %d from %s is matched to TP %d, which differs from the TP %d of already processed tracks." % (trk.index(), _name, _commonTP.index(), tp.index()))
241  return _commonTP
242  commonTP = _findCommonTP(trks1, commonTP, "lst1")
243  commonTP = _findCommonTP(trks2, commonTP, "lst2")
244 
245  # Need some tracks from trks1 and trks2 to print the TrackingParticle information
246  someTrk1 = trks1[0] if not trks1Empty else None
247  someTrk2 = trks2[0] if not trks2Empty else None
248 
249  for trk1 in trks1:
250  (matchedTrk2, ncommon) = _matchTracksByHits(trk1, trks2)
251 
252  # no more tracks in tp2
253  if matchedTrk2 is None:
254  if trk1.index() in trks1extra:
255  raise Exception("Track %d was found in trks1extra but matchedTrk2 is None, this should not happen" % trk1.index())
256  diff.extend(_makediff(trackPrinter.printTrack(trk1), []))
257  else: # diff trk1 to best-matching track from trks2
258  someTrk2 = matchedTrk2
259  trks2.remove(matchedTrk2)
260  tmp = trackPrinter.diff(trk1, matchedTrk2, diffTrackingParticles=False)
261  if diffByHitsOnly and _areSameTracks(trk1, matchedTrk2):
262  tmp.setDifference(False)
263  tmp.highlight(plus=(matchedTrk2.index() in trks2extra), minus=(trk1.index() in trks1extra))
264  diff.extend(tmp)
265 
266  for trk2 in trks2: # remaining tracks in trks2
267  if trk2.index() in trks2extra:
268  raise Exception("Track %d was found in trks2extra, but without matching track in trks1, this should not happen" % trk2.index())
269  diff.extend(_makediff([], trackPrinter.printTrack(trk2)))
270 
271  # finally add information of the trackingParticle
272  # easiest is to pass a track matched to the TP
273  tmp = _mapdiff(trackPrinter.printMatchedTrackingParticles, someTrk1, someTrk2)
274  tmp.setDifference(False) # we know the TP is the same, even if the "track match" information will differ
275  def _makere(lst):
276  r = []
277  for i in lst: r.extend([re.compile("Tracks:.*%d:"%i), re.compile("matched to tracks.*%d"%i)])
278  return r
279  plusre = _makere(trks2extra)
280  minusre = _makere(trks1extra)
281  tmp.highlightLines(plusre, minusre)
282  diff.extend(tmp)
283 
284  return diff
285 
287  def __init__(self):
288  super(_TrackAssociation, self).__init__()
289  self._trks1 = []
290  self._trks2 = []
293 
294  self._trks1Ind = set()
295  self._trks2Ind = set()
296  self._trks1OutsideListInd = set()
297  self._trks2OutsideListInd = set()
298 
299  def _extend(self, trks, name):
300  lst = getattr(self, name)
301  ind = getattr(self, name+"Ind")
302  for t in trks:
303  if not t.index() in ind:
304  lst.append(t)
305  ind.add(t.index())
306 
307  def extend(self, trks1=[], trks2=[], trks1OutsideList=[], trks2OutsideList=[]):
308  self.extendTrks1(trks1)
309  self.extendTrks2(trks2)
310  self.extendTrks1OutsideList(trks1OutsideList)
311  self.extendTrks2OutsideList(trks2OutsideList)
312 
313  def extendTrks1(self, trks):
314  self._extend(trks, "_trks1")
315 
316  def extendTrks2(self, trks):
317  self._extend(trks, "_trks2")
318 
319  def extendTrks1OutsideList(self, trks):
320  self._extend(trks, "_trks1OutsideList")
321 
322  def extendTrks2OutsideList(self, trks):
323  self._extend(trks, "_trks2OutsideList")
324 
325  def trks1(self): return self._trks1
326  def trks2(self): return self._trks2
327  def trks1OutsideList(self): return self._trks1OutsideList
328  def trks2OutsideList(self): return self._trks2OutsideList
329 
331  trkGen = itertools.chain(self._trks1, self._trks2)
332  try:
333  first = next(trkGen)
334  except StopIteration:
335  return False
336  if first.nMatchedTrackingParticles() != 1:
337  return False
338 
339  tpIndex = next(first.matchedTrackingParticleInfos()).trackingParticle().index()
340 
341  for t in trkGen:
342  if t.nMatchedTrackingParticles() != 1:
343  return False
344  if next(t.matchedTrackingParticleInfos()).trackingParticle().index() != tpIndex:
345  return False
346  return True
347 
348 
349  def merge(self, other):
350  self.extendTrks1(other._trks1)
351  self.extendTrks2(other._trks2)
352  self.extendTrks1OutsideList(other._trks1OutsideList)
353  self.extendTrks2OutsideList(other._trks2OutsideList)
354 
355  def minEta(self):
356  _min = lambda lst: min([t.eta() for t in lst])
357 
358  if len(self._trks1) > 0:
359  return _min(self._trks1)
360  if len(self._trks1OutsideList) > 0:
361  return _min(self._trks1OutsideList)
362  if len(self._trks2) > 0:
363  return _min(self._trks2)
364  if len(self._trks2_outsideList) > 0:
365  return _min(self._trks2OutsideList)
366  raise Exception("This _TrackAssociation is empty, minEta() makes no sense")
367 
368  def __str__(self):
369  s = lambda l: str([t.index() for t in l])
370  return s(self._trks1)+" "+s(self._trks2)+" "+s(self._trks1OutsideList)+" "+s(self._trks2OutsideList)
371 
373  trks1 = list(lst1)
374  trks2 = list(lst2)
375 
376  trks1Matcher = _TracksByHitsMatcher(trks1)
377  trks2Matcher = _TracksByHitsMatcher(trks2)
378 
379  # Used to have exactly the same Track objects for the same index
380  trks1Dict = {t.index(): t for t in trks1}
381  trks2Dict = {t.index(): t for t in trks2}
382 
383  # Bit of a hack...
384  tps1 = None
385  tps2 = None
386  if len(trks1) > 0:
387  tps1 = TrackingParticles(trks1[0]._tree)
388  if len(trks2) > 0:
389  tps2 = TrackingParticles(trks2[0]._tree)
390 
391  trkAssoc1 = {}
392  trkAssoc2 = {}
393 
394  def _getOrCreateAssoc(trk, d, **kwargs):
395  if trk.index() in d:
396  a = d[trk.index()]
397  else:
398  a = _TrackAssociation()
399  d[trk.index()] = a
400  a.extend(**kwargs)
401  return a
402 
403  while len(trks1) > 0:
404  trk1 = trks1.pop(0)
405  assoc1 = _getOrCreateAssoc(trk1, trkAssoc1, trks1=[trk1])
406 
407  # First associate via TP
408  if trk1.nMatchedTrackingParticles() > 0 and tps2:
409  matched = False
410 
411  for tpInfo1 in trk1.matchedTrackingParticleInfos():
412  tp1 = tpInfo1.trackingParticle()
413 
414  # Find possible duplicates within trks1
415  for trkInfo1 in tp1.matchedTrackInfos():
416  t1 = trkInfo1.track()
417  t1Index = t1.index()
418  if t1Index != trk1.index():
419  if t1Index in trks1Dict:
420  assoc1.extend(trks1=[t1]) # trk1 -> t1
421  _getOrCreateAssoc(t1, trkAssoc1, trks1=[t1, trk1]) # t1 -> trk1
422  #print "trk1 %d <-> t1 %d (TP)" % (trk1.index(), t1.index())
423  trks1.remove(trks1Dict[t1Index])
424  else:
425  #print "trk1 %d -> t1 %d (TP, not in list)" % (trk1.index(), t1.index())
426  assoc1.extend(trks1OutsideList=[t1]) # trk1 -> t1, if t1 is not in trks1
427 
428  # Then look for the same tp in trks2
429  tp2 = tps2[tp1.index()]
430  for trkInfo2 in tp2.matchedTrackInfos():
431  matched = True
432  t2 = trkInfo2.track()
433  t2Index = t2.index()
434  if t2Index in trks2Dict:
435  assoc1.extend(trks2=[t2]) # trk1 -> t2
436  _getOrCreateAssoc(t2, trkAssoc2, trks1=[trk1], trks2=[t2]) # t2 -> trk1
437  #print "trk1 %d <-> t2 %d (TP)" % (trk1.index(), t2.index())
438  try:
439  trks2.remove(trks2Dict[t2Index]) # can fail if t2 has already been matched via hits
440  except ValueError:
441  pass
442  else:
443  #print "trk1 %d -> t2 %d (TP, not in list)" % (trk1.index(), t2.index())
444  assoc1.extend(trks2OutsideList=[t2]) # trk1 -> t2, if t2 is not in trks2
445 
446  if matched:
447  continue
448 
449  # If no matching tracks in trks2 via TrackingParticles, then
450  # proceed finding the best match via hits
451  (matchedTrk2, ncommon) = trks2Matcher.match(trk1)
452  if matchedTrk2 is not None and ncommon >= 3:
453  assoc1.extend(trks2=[matchedTrk2])
454  assoc2 = _getOrCreateAssoc(matchedTrk2, trkAssoc2, trks1=[trk1], trks2=[matchedTrk2])
455  #print "trk1 %d <-> t2 %d (hits)" % (trk1.index(), matchedTrk2.index())
456  try:
457  trks2.remove(matchedTrk2) # can fail if matchedTrk2 has already been matched via TP
458  except ValueError:
459  pass
460 
461  (matchedTrk1, ncommon1) = trks1Matcher.match(matchedTrk2)
462  # if matchedTrk1 has TP, the link from matchedTrk1 -> matchedTrk2 will be created later
463  if (matchedTrk1.nMatchedTrackingParticles() == 0 or not tps2) and matchedTrk1.index() != trk1.index():
464  assoc2.extend(trks1=[matchedTrk1])
465  _getOrCreateAssoc(matchedTrk1, trkAssoc1, trks1=[matchedTrk1], trks2=[matchedTrk2])
466  #print "trk1 %d <-> t2 %d (hits, via t2)" % (matchedTrk1.index(), matchedTrk2.index())
467 
468  # no match
469 
470  # remaining tracks in trks2
471  for trk2 in trks2:
472  assoc2 = _getOrCreateAssoc(trk2, trkAssoc2, trks2=[trk2])
473  # collect duplicates
474  if trk2.nMatchedTrackingParticles() > 0:
475  for tpInfo2 in trk2.matchedTrackingParticleInfos():
476  tp2 = tpInfo2.trackingParticle()
477  for trkInfo2 in tp2.matchedTrackInfos():
478  t2 = trkInfo2.track()
479  t2Index = t2.index()
480  if t2Index in trks2Dict:
481  assoc2.extend(trks2=[t2])
482  #print "trk2 %d -> t2 %d (TP)" % (trk2.index(), t2.index())
483  else:
484  assoc2.extend(trks2OutsideList=[t2])
485  #print "trk2 %d -> t2 %d (TP, not in list)" % (trk2.index(), t2.index())
486 
487  # merge results
488  # any good way to avoid copy-past?
489  for ind, assoc in six.iteritems(trkAssoc1):
490  for t1 in assoc.trks1():
491  a = trkAssoc1[t1.index()]
492  assoc.merge(a)
493  a.merge(assoc)
494  for t2 in assoc.trks2():
495  a = trkAssoc2[t2.index()]
496  assoc.merge(a)
497  a.merge(assoc)
498  for ind, assoc in six.iteritems(trkAssoc2):
499  for t2 in assoc.trks2():
500  a = trkAssoc2[t2.index()]
501  assoc.merge(a)
502  a.merge(assoc)
503  for t1 in assoc.trks1():
504  a = trkAssoc1[t1.index()]
505  assoc.merge(a)
506  a.merge(assoc)
507 
508  for ind, assoc in itertools.chain(six.iteritems(trkAssoc1), six.iteritems(trkAssoc2)):
509  #if ind in [437, 1101]:
510  # print "----"
511  # print ind, [t.index() for t in assoc.trks1()], [t.index() for t in assoc.trks2()]
512  for t1 in assoc.trks1():
513  a = trkAssoc1[t1.index()]
514  assoc.merge(a)
515  a.merge(assoc)
516 
517  #if ind in [437, 1101]:
518  # print ind, [t.index() for t in assoc.trks1()], [t.index() for t in assoc.trks2()]
519 
520  for t2 in assoc.trks2():
521  a = trkAssoc2[t2.index()]
522  assoc.merge(a)
523  a.merge(assoc)
524  #if ind in [437, 1101]:
525  # print ind, [t.index() for t in assoc.trks1()], [t.index() for t in assoc.trks2()]
526  # print "####"
527 
528  # collapse to a single collection of associations
529  allAssocs = []
530  while len(trkAssoc1) > 0:
531  (t1Index, assoc) = trkAssoc1.popitem()
532 
533  #if t1Index == 1299:
534  # print t1Index, [t.index() for t in assoc.trks2()]
535  for t1 in assoc.trks1():
536  if t1.index() == t1Index: continue
537  trkAssoc1.pop(t1.index())
538  for t2 in assoc.trks2():
539  trkAssoc2.pop(t2.index())
540  allAssocs.append(assoc)
541  while len(trkAssoc2) > 0:
542  (t2Index, assoc) = trkAssoc2.popitem()
543  if len(assoc.trks1()) > 0:
544  raise Exception("len(assoc.trks1()) %d != 0 !!! %s for t2 %d" % (len(assoc.trks1()), str([t.index() for t in assoc.trks1()]), t2Index))
545  for t2 in assoc.trks2():
546  if t2.index() == t2Index: continue
547  trkAssoc2.pop(t2.index())
548  allAssocs.append(assoc)
549 
550  return allAssocs
551 
552 def diffTrackListsGeneric(trackPrinter, lst1, lst2, ignoreAdditionalLst2=False):
553  associations = _associateTracksByTrackingParticlesAndHits(lst1, lst2)
554 
555  # sort in eta
556  associations.sort(key=methodcaller("minEta"))
557 
558  diff = _DiffResult()
559  for assoc in associations:
560  if assoc.hasCommonTrackingParticle():
561  if len(assoc.trks1()) == 0 and ignoreAdditionalLst2:
562  continue
563 
564  tmp = diffTrackListsFromSameTrackingParticle(trackPrinter, assoc.trks1(), assoc.trks2(), lst1extra=assoc.trks1OutsideList(), lst2extra=assoc.trks2OutsideList(), diffByHitsOnly=True)
565  if tmp.hasDifference():
566  diff.extend(tmp)
567  diff.extend([" "])
568  elif len(assoc.trks1()) == 1 and len(assoc.trks2()) == 1:
569  trk1 = assoc.trks1()[0]
570  trk2 = assoc.trks2()[0]
571 
572  if not _areSameTracks(trk1, trk2):
573  diff.extend(trackPrinter.diff(trk1, trk2))
574  diff.extend([" "])
575  elif len(assoc.trks2()) == 0:
576  for t in assoc.trks1():
577  diff.extend(trackPrinter.diff(t, None))
578  diff.extend([" "])
579  elif len(assoc.trks1()) == 0:
580  if ignoreAdditionalLst2:
581  continue
582  for t in assoc.trks1():
583  diff.extend(trackPrinter.diff(None, t))
584  diff.extend([" "])
585  else:
586  # needs to be rather generic, let's start by sorting by the innermost hit
587  trks1 = list(assoc.trks1())
588  trks2 = list(assoc.trks2())
589  trks1.sort(key=lambda t: next(t.hits()).r())
590  trks2.sort(key=lambda t: next(t.hits()).r())
591 
592  # then calculate number of shared hits for each pair
593  ncommon = []
594  for i1, t1 in enumerate(trks1):
595  for i2, t2 in enumerate(trks2):
596  ncommon.append( (i1, i2, _commonHits(t1, t2)) )
597 
598  # sort that by number of common hits, descending order
599  ncommon.sort(key=itemgetter(2), reverse=True)
600 
601  # then make the diffs starting from the pair with largest number of common hits
602  pairs = [None]*len(trks1)
603  usedT2 = [False]*len(trks2)
604  for i1, i2, ncom in ncommon:
605  if pairs[i1] is None:
606  pairs[i1] = i2
607  usedT2[i2] = True
608 
609  for i1, i2 in enumerate(pairs):
610  t1 = trks1[i1]
611  t2 = trks2[i2]
612  diff.extend(trackPrinter.diff(t1, t2))
613  for i2, used in enumerate(usedT2):
614  if not used:
615  diff.extend(trackPrinter.diff(None, trks2[i2]))
616  diff.extend([" "])
617 
618  return diff
619 
620 def _formatHitDiffForTwiki(diffHits, prefix):
621  line_re = re.compile("(?P<sign>[ \-+])\s+(?P<det>[a-zA-Z]+)(?P<lay>\d+)\D*?(\((?P<missing>missing|inactive)\))?\s+\d+")
622 
623  summary = []
624  prevdet = ""
625  prevsign = " "
626  diffLines = diffHits.lines()
627 
628  # skip anything before the first line with "hits"
629  for line in diffLines:
630  if "hits" in line:
631  break
632 
633  header = True
634  for line in diffLines:
635  # skip multiple occurrances of "hits" line, but only until
636  # first line without "hits" is encountered
637  if header:
638  if "hits" in line:
639  continue
640  else:
641  header = False
642 
643  m = line_re.search(line)
644  if not m:
645  break
646  raise Exception("regex not found from line %s" % line.rstrip())
647  sign = m.group("sign")
648  det = m.group("det")
649  lay = m.group("lay")
650 
651  if det != prevdet:
652  if prevsign != " ":
653  summary.append("%ENDCOLOR%")
654  prevsign = " "
655  summary.extend([" ", det])
656  prevdet = det
657 
658  if sign != prevsign:
659  if prevsign != " ":
660  summary.append("%ENDCOLOR%")
661  if sign == "-":
662  summary.append("%RED%")
663  elif sign == "+":
664  summary.append("%GREEN%")
665  prevsign = sign
666 
667  #print sign, det, lay
668  #if len(summary) > 0:
669  # print " ", summary[-1]
670 
671  #if det != prevdet:
672  # if prevsign != " ":
673  # #if len(summary) > 0:
674  # # if
675  # summary.append("%ENDCOLOR")
676  # summary.extend([" ", det])
677  # if prevsign == "-":
678  # summary.append("%RED%")
679  # elif prevsign == "+":
680  # summary.append("%GREEN%")
681  # prevdet = det
682  summary.append(lay)
683  if m.group("missing"):
684  if m.group("missing") == "missing":
685  summary.append("(m)")
686  elif m.group("missing") == "inactive":
687  summary.append("(i)")
688 
689  if prevsign != " ":
690  summary.append("%ENDCOLOR%")
691  # prune "changed" missing/inactive hits
692  i = 2
693  while i < len(summary)-5:
694  if summary[i] == "(i)" or summary[i] == "(m)":
695  if summary[i-2] == "%RED%" and summary[i+1] == "%ENDCOLOR%" and summary[i+2] == "%GREEN%" and summary[i+3] == summary[i-1] and summary[i+4] == summary[i] and summary[i+5] == "%ENDCOLOR%":
696  summary[i-2:i+6] = [summary[i-1], summary[i]]
697  i += 1
698 
699  line = " "+"".join(summary)
700  return ["?"+prefix+line]
701 
702 # Common detailed printout helpers
704  summary = ""
705 
706  prevdet = 0
707  for hit in hits:
708  det = hit.subdet()
709  lay = hit.layer()
710 
711  if det != prevdet:
712  summary += " "+SubDet.toString(det)
713  prevdet = det
714 
715  summary += str(lay)
716  if isinstance(hit, InvalidHit):
717  summary += "(%s)"%InvalidHit.Type.toString(hit.type())[0]
718 
719  return summary
720 
722  def __init__(self, indent=0):
723  self._prefix = " "*indent
724  self._backup = []
725 
726  def _indent(self, num):
727  if num > 0:
728  self._prefix += " "*num
729  elif num < 0:
730  self._prefix = self._prefix[:num]
731 
732  def indent(self, num):
733  self._backup.append(self._prefix)
734  self._indent(num)
735 
736  def setIndentFrom(self, printer, adjust=0):
737  self._backup.append(self._prefix)
738  self._prefix = printer._prefix
739  self._indent(adjust)
740 
741  def restoreIndent(self):
742  self._prefix = self._backup.pop()
743 
745  def __init__(self, indent=0):
746  super(_RecHitPrinter, self).__init__(indent)
747 
748  def _printHits(self, hits):
749  lst = []
750  for hit in hits:
751  matched = ""
752  glued = ""
753  coord = ""
754  if hit.isValidHit():
755  if hasattr(hit, "matchedSimHitInfos"):
756  matched = " from %s " % HitSimType.toString(hit.simType())
757  matches = []
758  hasChargeFraction = False
759  for shInfo in hit.matchedSimHitInfos():
760  m = "%d:%d" % (shInfo.simHit().trackingParticle().index(), shInfo.simHit().index())
761  if hasattr(shInfo, "chargeFraction"):
762  m += "(%.1f)"%(shInfo.chargeFraction()*100)
763  hasChargeFraction = True
764  matches.append(m)
765  if len(matches) == 0:
766  matched += "not matched to any TP/SimHit"
767  else:
768  matched += "matched to TP:SimHit"
769  if hasChargeFraction:
770  matched += "(%)"
771  matched += " "+",".join(matches)
772 
773  coord = "x,y,z %f,%f,%f" % (hit.x(), hit.y(), hit.z())
774  if isinstance(hit, GluedHit):
775  glued = "monoHit %d stereoHit %d " % (hit.monoHit().index(), hit.stereoHit().index())
776 
777  lst.append(self._prefix+"{layer} {hit} detid {detid} {detidStr} {glued}{coord}{matched}".format(layer=hit.layerStr(), hit=hit.index(),
778  detid=hit.detId(), detidStr=hit.detIdStr(),
779  glued=glued, coord=coord, matched=matched))
780  return lst
781 
783  def __init__(self, trackingParticles, trackingParticlePrinter, bestMatchingTrackingParticle):
784  self._trackingParticles = trackingParticles
785  self._trackingParticlePrinter = trackingParticlePrinter
786  self._bestMatchingTrackingParticle = bestMatchingTrackingParticle
787 
790 
791  def _printTrackingParticles(self, prefix, tps, header):
792  lst = []
793  if self._trackingParticlePrinter is None:
794  lst.append(prefix+header+" "+",".join([str(tp.index()) for tp in tps]))
795  else:
796  lst.append(prefix+header)
797  for tp in tps:
798  lst.extend(self._trackingParticlePrinter.printTrackingParticle(tp))
799  lst.extend(self._trackingParticlePrinter.printHits(tp))
800  lst.extend(self._trackingParticlePrinter.printMatchedTracks(tp, useTrackPrinter=False))
801  return lst
802 
803  def printMatchedTrackingParticles(self, prefix, track):
804  lst = []
805  if not self._trackingParticles:
806  return lst
807 
808  pfx = prefix+" "
809  if self._trackingParticlePrinter is not None:
810  self._trackingParticlePrinter.indent(len(pfx)+1)
811 
812  if track.nMatchedTrackingParticles() == 0:
814  bestTP = track.bestMatchingTrackingParticle()
815  if bestTP is not None:
816  lst.extend(self._printTrackingParticles(pfx, [bestTP], "not matched to any TP, but a following TP with >= 3 matched hits is found (shared hit fraction %.2f)" % track.bestMatchingTrackingParticleShareFrac()))
817  else:
818  lst.append(prefix+"not matched to any TP")
819  else:
820  lst.append(prefix+"not matched to any TP")
821  else:
822  lst.extend(self._printTrackingParticles(pfx, [tpInfo.trackingParticle() for tpInfo in track.matchedTrackingParticleInfos()], "matched to TPs"))
823 
824  if self._trackingParticlePrinter is not None:
825  self._trackingParticlePrinter.restoreIndent()
826 
827  return lst
828 
830  def __init__(self, indent=0, hits=True, trackingParticles=False, trackingParticlePrinter=None, bestMatchingTrackingParticle=True):
831  super(SeedPrinter, self).__init__(indent)
832  self._hits = hits
833  self._trackingParticleMatchPrinter = _TrackingParticleMatchPrinter(trackingParticles, trackingParticlePrinter, bestMatchingTrackingParticle)
834 
835  def printHeader(self, seed):
836  lst = []
837  track = seed.track()
838  if track.isValid():
839  madeTrack = "made track %d" % track.index()
840  else:
841  madeTrack = "did not make a track, stopReason %s" % SeedStopReason.toString(seed.stopReason())
842  if seed.stopReason() == SeedStopReason.NOT_STOPPED:
843  madeTrack += " (usually this means that the track was reconstructed, but rejected by the track selection)"
844 
845  lst.append(self._prefix+"Seed %d algo %s %s" % (seed.indexWithinAlgo(), Algo.toString(seed.algo()), madeTrack))
846  lst.append(self._prefix+" starting state: pT %f local pos x,y %f,%f mom x,y,z %f,%f,%f" % (seed.statePt(), seed.stateTrajX(), seed.stateTrajY(), seed.stateTrajPx(), seed.stateTrajPy(), seed.stateTrajPz()))
847  return lst
848 
849  def printHits(self, seed):
850  lst = []
851  if self._hits:
852  lst.append(self._prefix+" hits"+_hitPatternSummary(seed.hits()))
853  self.indent(2)
854  lst.extend(self._printHits(seed.hits()))
855  self.restoreIndent()
856  return lst
857 
859  return self._trackingParticleMatchPrinter.printMatchedTrackingParticles(self._prefix, seed)
860 
861  def printSeed(self, seed):
862  lst = []
863  lst.extend(self.printHeader(seed))
864  lst.extend(self.printHits(seed))
865  lst.extend(self.printMatchedTrackingParticles(seed))
866  return lst
867 
868  def __call__(self, seed, out=sys.stdout):
869  if isinstance(out, list):
870  lst = out
871  else:
872  lst = []
873 
874  lst.extend(self.printSeed(seed))
875 
876  if not isinstance(out, list):
877  for line in lst:
878  out.write(line),
879  out.write("\n")
880 
881  def diff(self, seed1, seed2, diffForTwiki=False, diffTrackingParticles=False):
882  if seed1 is None:
883  return _makediff([], self.printSeed(seed2))
884  if seed2 is None:
885  return _makediff(self.printSeed(seed1), [])
886 
887  ret = _DiffResult()
888  ret.extend(_mapdiff(self.printHeader, seed1, seed2))
889  diffHits = _mapdiff(self.printHits, seed1, seed2)
890  ret.extend(diffHits)
891  if diffForTwiki:
892  ret.extend(_formatHitDiffForTwiki(diffHits, self._prefix))
893  if diffTrackingParticles:
894  ret.extend(_mapdiff(self.printMatchedTrackingParticles, seed1, seed2))
895  return ret
896 
898  def __init__(self, indent=0, hits=True, seedPrinter=SeedPrinter(), trackingParticles=True, trackingParticlePrinter=None, bestMatchingTrackingParticle=True, diffForTwiki=False):
899  super(TrackPrinter, self).__init__(indent)
900  self._hits = hits
901  self._seedPrinter = seedPrinter
902  self._trackingParticleMatchPrinter = _TrackingParticleMatchPrinter(trackingParticles, trackingParticlePrinter, bestMatchingTrackingParticle)
903  self._diffForTwiki = diffForTwiki
904 
905  def printHeader(self, track):
906  lst = []
907  lst.append(self._prefix+"Track %d pT %f eta %f phi %f dxy %f err %f dz %f err %f" % (track.index(), track.pt(), track.eta(), track.phi(), track.dxy(), track.dxyErr(), track.dz(), track.dzErr()))
908 
909  hp = "loose"
910  if track.isHP():
911  hp = "HP"
912 
913  algo = track.algo()
914  oriAlgo = track.originalAlgo()
915  algos = []
916  algoMask = track.algoMask()
917  for i in range(Algo.algoSize):
918  if algoMask & 1:
919  algos.append(Algo.toString(i))
920  algoMask = algoMask >> 1
921  algoMaskStr = ""
922  if len(algos) >= 2:
923  algoMaskStr = " algoMask "+",".join(algos)
924 
925 
926  lst.append(self._prefix+" pixel hits %d strip hits %d chi2/ndof %f" % (track.nPixel(), track.nStrip(), track.nChi2()))
927  lst.append(self._prefix+" is %s algo %s originalAlgo %s%s stopReason %s" % (hp, Algo.toString(track.algo()), Algo.toString(track.originalAlgo()), algoMaskStr, StopReason.toString(track.stopReason())))
928  lst.append(self._prefix+" px %f py %f pz %f p %f" % (track.px(), track.py(), track.pz(), math.sqrt(track.px()**2+track.py()**2+track.pz()**2)))
929  if self._trackingParticleMatchPrinter.bestMatchingTrackingParticle():
930  bestTP = track.bestMatchingTrackingParticle()
931  if bestTP:
932  lst.append(self._prefix+" best-matching TP %d" % bestTP.index())
933  lst.append(self._prefix+" shared hits %d reco denom %.3f sim denom %.3f sim cluster denom %.3f" % (track.bestMatchingTrackingParticleShareFrac()*track.nValid(), track.bestMatchingTrackingParticleShareFrac(), track.bestMatchingTrackingParticleShareFracSimDenom(), track.bestMatchingTrackingParticleShareFracSimClusterDenom()))
934  lst.append(self._prefix+" matching chi2/ndof %f" % track.bestMatchingTrackingParticleNormalizedChi2())
935  lst.append(self._prefix+" pulls pt %f theta %f phi %f dxy %f dz %f" % (track.ptPull(), track.thetaPull(), track.phiPull(), track.dxyPull(), track.dzPull()))
936  return lst
937 
938  def printHits(self, track):
939  lst = []
940  if self._hits:
941  lst.append(self._prefix+" hits"+_hitPatternSummary(track.hits()))
942  self.indent(2)
943  lst.extend(self._printHits(track.hits()))
944  self.restoreIndent()
945  return lst
946 
947  def printSeed(self, track):
948  lst = []
949  if self._seedPrinter:
950  self._seedPrinter.setIndentFrom(self, adjust=1)
951  lst.extend(self._seedPrinter.printSeed(track.seed()))
952  self._seedPrinter.restoreIndent()
953  return lst
954 
955  def diffSeeds(self, track1, track2):
956  ret = _DiffResult()
957  if self._seedPrinter:
958  self._seedPrinter.setIndentFrom(self, adjust=1)
959  ret.extend(self._seedPrinter.diff(track1.seed(), track2.seed(), self._diffForTwiki))
960  self._seedPrinter.restoreIndent()
961  return ret
962 
963  def printTrack(self, track):
964  lst = self.printHeader(track)
965  lst.extend(self.printHits(track))
966  lst.extend(self.printSeed(track))
967  return lst
968 
970  return self._trackingParticleMatchPrinter.printMatchedTrackingParticles(self._prefix, track)
971 
973  lst = []
974  lst.extend(self.printTrack(track))
975  lst.extend(self.printMatchedTrackingParticles(track))
976  return lst
977 
978  def __call__(self, track, out=sys.stdout):
979  if isinstance(out, list):
980  lst = out
981  else:
982  lst = []
983 
984  lst.extend(self.printTrackAndMatchedTrackingParticles(track))
985 
986  if not isinstance(out, list):
987  for line in lst:
988  out.write(line)
989  out.write("\n")
990 
991  def diff(self, track1, track2, diffTrackingParticles=True):
992  if track1 is None:
993  lst = self.printTrack(track2) + self.printMatchedTrackingParticles(track2)
994  return _makediff([], lst)
995  if track2 is None:
996  lst = self.printTrack(track1) + self.printMatchedTrackingParticles(track1)
997  return _makediff(lst, [])
998 
999  ret = _DiffResult()
1000  ret.extend(_mapdiff(self.printHeader, track1, track2))
1001  if self._diffForTwiki:
1002  trk1TPs = [tpInfo.trackingParticle() for tpInfo in track1.matchedTrackingParticleInfos()]
1003  trk2TPs = [tpInfo.trackingParticle() for tpInfo in track2.matchedTrackingParticleInfos()]
1004 
1005  pt_pull1 = "None"
1006  pt_pull2 = "None"
1007  dxy_pull1 = "None"
1008  dxy_pull2 = "None"
1009  dz_pull1 = "None"
1010  dz_pull2 = "None"
1011 
1012  ptPull1 = track1.ptPull()
1013  ptPull2 = track2.ptPull()
1014  if ptPull1 is not None and ptPull2 is not None:
1015  fmt = "{pull:.3g}"
1016  pt_pull1 = fmt.format(pull=ptPull1)
1017  pt_pull2 = fmt.format(pull=ptPull2)
1018  dxy_pull1 = fmt.format(pull=track1.dxyPull())
1019  dxy_pull2 = fmt.format(pull=track2.dxyPull())
1020  dz_pull1 = fmt.format(pull=track1.dzPull())
1021  dz_pull2 = fmt.format(pull=track2.dzPull())
1022 
1023  lst = [
1024  self._prefix+" parameters",
1025  self._prefix+" pt %RED%{pt1:.3g}%ENDCOLOR% %GREEN%{pt2:.3g}%ENDCOLOR%".format(pt1=track1.pt(), pt2=track2.pt()),
1026  ]
1027  if pt_pull1 != "None":
1028  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=pt_pull1, pull2=pt_pull2))
1029  lst.extend([
1030  self._prefix+" eta %RED%{eta1:.3g}%ENDCOLOR% %GREEN%{eta2:.3g}%ENDCOLOR%".format(eta1=track1.eta(), eta2=track2.eta()),
1031  self._prefix+" phi %RED%{phi1:.3g}%ENDCOLOR% %GREEN%{phi2:.3g}%ENDCOLOR%".format(phi1=track1.phi(), phi2=track2.phi()),
1032  self._prefix+" dxy %RED%{dxy1:.3g}%ENDCOLOR% %GREEN%{dxy2:.3g}%ENDCOLOR% ({dxy1rel:.2f}*err1, {dxy2rel:.2f}*err2)".format(dxy1=track1.dxy(), dxy2=track2.dxy(), dxy1rel=(track2.dxy()-track1.dxy())/track1.dxyErr(), dxy2rel=(track2.dxy()-track1.dxy())/track2.dxyErr()),
1033  ])
1034  if dxy_pull1 != "None":
1035  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=dxy_pull1, pull2=dxy_pull2))
1036  lst.extend([
1037  self._prefix+" dz %RED%{dz1:.3g}%ENDCOLOR% %GREEN%{dz2:.3g}%ENDCOLOR% ({dz1rel:.2f}*err1, {dz2rel:.2f}*err2)".format(dz1=track1.dz(), dz2=track2.dz(), dz1rel=(track2.dz()-track1.dz())/track1.dzErr(), dz2rel=(track2.dz()-track1.dz())/track2.dzErr()),
1038  ])
1039  if dz_pull1 != "None":
1040  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=dz_pull1, pull2=dz_pull2))
1041  lst.extend([
1042  self._prefix+" chi2/ndof %RED%{chi1:.3g}%ENDCOLOR% %GREEN%{chi2:.3g}%ENDCOLOR%".format(chi1=track1.nChi2(), chi2=track2.nChi2()),
1043  ])
1044  ret.extend(_makediff(lst, lst, equalPrefix="?"))
1045 
1046  diffHits = _mapdiff(self.printHits, track1, track2)
1047  ret.extend(diffHits)
1048  if self._hits and self._diffForTwiki:
1049  ret.extend(_formatHitDiffForTwiki(diffHits, self._prefix))
1050 
1051  ret.extend(self.diffSeeds(track1, track2))
1052  if diffTrackingParticles:
1053  ret.extend(_mapdiff(self.printMatchedTrackingParticles, track1, track2))
1054  return ret
1055 
1057  def __init__(self, indent=0, parentage=True, hits=True, tracks=True, trackPrinter=None, bestMatchingTrack=True, seedPrinter=SeedPrinter()):
1058  super(TrackingParticlePrinter, self).__init__(indent)
1059  self._parentage = parentage
1060  self._hits = hits
1061  self._tracks = tracks
1062  self._trackPrinter = trackPrinter
1063  self._bestMatchingTrack = bestMatchingTrack
1064  self._seedPrinter = seedPrinter
1065 
1066  def _printTP(self, tp):
1067  genIds = ""
1068  if len(tp.genPdgIds()) > 0:
1069  genIds = " genPdgIds "+",".join([str(pdgId) for pdgId in tp.genPdgIds()])
1070  fromB = ""
1071  if tp.isFromBHadron():
1072  fromB = " from B hadron"
1073  return [
1074  self._prefix+"TP %d pdgId %d%s%s ev:bx %d:%d pT %f eta %f phi %f" % (tp.index(), tp.pdgId(), genIds, fromB, tp.event(), tp.bunchCrossing(), tp.pt(), tp.eta(), tp.phi()),
1075  self._prefix+" pixel hits %d strip hits %d numberOfTrackerHits() %d associated reco clusters %d dxy %f dz %f" % (tp.nPixel(), tp.nStrip(), tp.nTrackerHits(), tp.nRecoClusters(), tp.pca_dxy(), tp.pca_dz())
1076  ]
1077 
1078 
1079  def _parentageChain(self, tp):
1080  lst = []
1081  prodVtx = tp.parentVertex()
1082  if prodVtx.nSourceTrackingParticles() == 1:
1083  lst.extend(self._printTP(next(prodVtx.sourceTrackingParticles())))
1084  elif prodVtx.nSourceTrackingParticles() >= 2:
1085  self.indent(1)
1086  for tp in prodVtx.sourceTrackingParticles():
1087  self._printTP(tp, out)
1088  self.indent(1)
1089  lst.extend(self._parentageChain(tp))
1090  self.indent(-1)
1091  self.indent(-1)
1092  return lst
1093 
1094  def printTrackingParticle(self, tp):
1095  lst = []
1096  lst.extend(self._printTP(tp))
1097  if self._parentage:
1098  if tp.parentVertex().nSourceTrackingParticles() > 0:
1099  lst.append(self._prefix+" parentage chain")
1100  self.indent(2)
1101  lst.extend(self._parentageChain(tp))
1102  self.indent(-2)
1103  return lst
1104 
1105  def printHits(self, tp):
1106  lst = []
1107  if self._hits:
1108  lst.append(self._prefix+" sim hits"+_hitPatternSummary(tp.simHits()))
1109  for simhit in tp.simHits():
1110  tmp = []
1111  for h in simhit.hits():
1112  tmp.append(",".join([str(trk.index()) for trk in h.tracks()]) + ":%d"%h.index())
1113  if len(tmp) == 0:
1114  matched = "not matched to any Track/RecHit"
1115  else:
1116  matched = "matched to Tracks:RecHits "+";".join(tmp)
1117 
1118  lst.append(self._prefix+" %s %d pdgId %d process %d detId %d %s x,y,z %f,%f,%f %s" % (simhit.layerStr(), simhit.index(), simhit.particle(), simhit.process(), simhit.detId(), simhit.detIdStr(), simhit.x(), simhit.y(), simhit.z(), matched))
1119  return lst
1120 
1122  return [self._prefix+" matched to tracks"]
1123 
1124  def _printMatchedTracks(self, tracks, header=None, useTrackPrinter=True):
1125  lst = []
1126  if header is not None:
1127  lst.append(self._prefix+" "+header)
1128  else:
1129  lst.extend(self._printMatchedTracksHeader())
1130  if self._trackPrinter is None or not useTrackPrinter:
1131  lst[-1] += " "+",".join([str(track.index()) for track in tracks])
1132  else:
1133  self._trackPrinter.indent(2)
1134  for track in tracks:
1135  lst.extend(self._trackPrinter.printTrack(track))
1136  self._trackPrinter.restoreIndent()
1137  return lst
1138 
1139  def printMatchedTracks(self, tp, useTrackPrinter=True):
1140  lst = []
1141  if tp.nMatchedTracks() == 0:
1142  header = "not matched to any track"
1143  lst.append(self._prefix+" "+header)
1144  if self._bestMatchingTrack:
1145  bestTrack = tp.bestMatchingTrack()
1146  if bestTrack is not None:
1147  lst.pop()
1148  lst.extend(self._printMatchedTracks([bestTrack], header+", but a following track with >= 3 matched hits is found", useTrackPrinter=useTrackPrinter))
1149  else:
1150  lst.extend(self._printMatchedTracks([trkInfo.track() for trkInfo in tp.matchedTrackInfos()], useTrackPrinter=useTrackPrinter))
1151  return lst
1152 
1153  def diffMatchedTracks(self, tp1, tp2):
1154  ntrk1 = tp1.nMatchedTracks()
1155  ntrk2 = tp2.nMatchedTracks()
1156 
1157  if ntrk1 == 0 or ntrk2 == 0 or self._trackPrinter is None:
1158  return _makediff(self.printMatchedTracks(tp1), self.printMatchedTracks(tp2))
1159 
1160  self._trackPrinter.indent(2)
1161 
1163  trks1 = [trkInfo1.track() for trkInfo1 in tp1.matchedTrackInfos()]
1164  trks2 = [trkInfo2.track() for trkInfo2 in tp2.matchedTrackInfos()]
1165  #for trkInfo1 in tp1.matchedTrackInfos():
1166  # trk1 = trkInfo1.track()
1167  # matchedTrk2 = _matchTracksByHits(trk1, trks2)
1168  #
1169  # if matchedTrk2 is None: # no more tracks in tp2
1170  # diff.extend(_makediff(self._trackPrinter.printTrack(trk1), []))
1171  # else: # diff trk1 to best-matching track from tp2
1172  # trks2.remove(matchedTrk2)
1173  # diff.extend(self._trackPrinter.diff(trk1, matchedTrk2))
1174  #
1175  #for trk2 in trks2: # remaining tracks in tp2
1176  # diff.extend(_makediff([], self._trackPrinter.printTrack(trk2)))
1177  diff.extend(diffTrackListsFromSameTrackingParticle(self._trackPrinter, trks1, trks2))
1178 
1179  self._trackPrinter.restoreIndent()
1180  return diff
1181 
1183  return [self._prefix+ " not matched to any seed"]
1184 
1186  return [self._prefix+" matched to seeds"]
1187 
1188  def printMatchedSeeds(self, tp):
1189  lst = []
1190  if self._seedPrinter:
1191  if tp.nMatchedSeeds() == 0:
1192  lst.extend(self._printMatchedSeeds0())
1193  else:
1194  lst.extend(self._printMatchedSeedsHeader())
1195  self._seedPrinter.setIndentFrom(self, adjust=2)
1196  for seedInfo in tp.matchedSeedInfos():
1197  lst.extend(self._seedPrinter.printSeed(seedInfo.seed()))
1198  self._seedPrinter.restoreIndent()
1199  return lst
1200 
1201  def diffMatchedSeeds(self, tp1, tp2):
1202  if not self._seedPrinter:
1203  return []
1204 
1205  nseed1 = tp1.nMatchedSeeds()
1206  nseed2 = tp2.nMatchedSeeds()
1207  if nseed1 == 0 or nseed2 == 0:
1208  return _makediff(self.printMatchedSeeds(tp1), self.printMatchedSeeds(tp2))
1209 
1210  self._seedPrinter.setIndentFrom(self, adjust=2)
1211 
1213  seeds2 = [seedInfo2.seed() for seedInfo2 in tp2.matchedSeedInfos()]
1214  for seedInfo1 in tp1.matchedSeedInfos():
1215  seed1 = seedInfo1.seed()
1216  matchedSeed2 = _matchTracksByHits(seed1, seeds2)[0]
1217 
1218  if matchedSeed2 is None: # no more seeds in tp2
1219  diff.extend(_makediff(self._seedPrinter.printSeed(seed1), []))
1220  else: # diff seed1 to best-matching seed from tp2
1221  seeds2.remove(matchedSeed2)
1222  diff.extend(_makediff(self._seedPrinter.printSeed(seed1), self._seedPrinter.printSeed(matchedSeed2)))
1223 
1224  for seed2 in seeds2: # remiaining seeds in tp2
1225  diff.extend(_makediff([], self._seedPrinter.printSeed(seed2)))
1226 
1227  self._seedPrinter.restoreIndent()
1228 
1229  return diff
1230 
1231  def __call__(self, tp, out=sys.stdout):
1232  if isinstance(out, list):
1233  lst = out
1234  else:
1235  lst = []
1236 
1237  lst.extend(self.printTrackingParticle(tp))
1238  lst.extend(self.printHits(tp))
1239  lst.extend(self.printMatchedTracks(tp))
1240  lst.extend(self.printMatchedSeeds(tp))
1241 
1242  for line in lst:
1243  out.write(line)
1244  out.write("\n")
1245 
1246  def diff(self, tp1, tp2):
1247  ret = _DiffResult()
1248  ret.extend(_mapdiff(self.printTrackingParticle, tp1, tp2))
1249  ret.extend(_mapdiff(self.printHits, tp1, tp2))
1250  ret.extend(self.diffMatchedTracks(tp1, tp2))
1251  ret.extend(self.diffMatchedSeeds(tp1, tp2))
1252  return ret
1253 
def _mapdiff(func, obj1, obj2)
def __init__(self, trackingParticles, trackingParticlePrinter, bestMatchingTrackingParticle)
def setIndentFrom(self, printer, adjust=0)
def __init__(self, indent=0, parentage=True, hits=True, tracks=True, trackPrinter=None, bestMatchingTrack=True, seedPrinter=SeedPrinter())
def highlightLines(self, plusregexs=[], minusregexs=[])
def _highlightLine(self, line, plus, minus)
def diff(self, track1, track2, diffTrackingParticles=True)
def _areSameTracks(trk1, trk2)
def printTrackAndMatchedTrackingParticles(self, track)
def _makediff(list1, list2, equalPrefix=" ")
def __init__(self, indent=0, hits=True, seedPrinter=SeedPrinter(), trackingParticles=True, trackingParticlePrinter=None, bestMatchingTrackingParticle=True, diffForTwiki=False)
def _formatHitDiffForTwiki(diffHits, prefix)
def setDifference(self, diff=True)
def highlight(self, plus=False, minus=False)
def __call__(self, seed, out=sys.stdout)
def __init__(self, diff=[], hasDifference=False)
def diffTrackListsFromSameTrackingParticle(trackPrinter, lst1, lst2, lst1extra=[], lst2extra=[], diffByHitsOnly=False)
def __init__(self, indent=0, hits=True, trackingParticles=False, trackingParticlePrinter=None, bestMatchingTrackingParticle=True)
def _matchTracksByHits(reftrk, trklist)
def _commonHits(trk1, trk2)
def _printTrackingParticles(self, prefix, tps, header)
T min(T a, T b)
Definition: MathUtil.h:58
def diffTrackListsGeneric(trackPrinter, lst1, lst2, ignoreAdditionalLst2=False)
def _printMatchedTracks(self, tracks, header=None, useTrackPrinter=True)
def printMatchedTrackingParticles(self, track)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def __call__(self, track, out=sys.stdout)
def printMatchedTracks(self, tp, useTrackPrinter=True)
def extend(self, trks1=[], trks2=[], trks1OutsideList=[], trks2OutsideList=[])
def _difflist(list1, list2)
def diffSeeds(self, track1, track2)
def diff(self, seed1, seed2, diffForTwiki=False, diffTrackingParticles=False)
#define str(s)
def _associateTracksByTrackingParticlesAndHits(lst1, lst2)
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
def printMatchedTrackingParticles(self, seed)