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