CMS 3D CMS Logo

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