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 (shared hit fraction %.2f)" % track.bestMatchingTrackingParticleShareFrac()))
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  bestTP = track.bestMatchingTrackingParticle()
929  if bestTP:
930  lst.append(self._prefix+" best-matching TP %d" % bestTP.index())
931  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()))
932  lst.append(self._prefix+" matching chi2/ndof %f" % track.bestMatchingTrackingParticleNormalizedChi2())
933  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()))
934  return lst
935 
936  def printHits(self, track):
937  lst = []
938  if self._hits:
939  lst.append(self._prefix+" hits"+_hitPatternSummary(track.hits()))
940  self.indent(2)
941  lst.extend(self._printHits(track.hits()))
942  self.restoreIndent()
943  return lst
944 
945  def printSeed(self, track):
946  lst = []
947  if self._seedPrinter:
948  self._seedPrinter.setIndentFrom(self, adjust=1)
949  lst.extend(self._seedPrinter.printSeed(track.seed()))
950  self._seedPrinter.restoreIndent()
951  return lst
952 
953  def diffSeeds(self, track1, track2):
954  ret = _DiffResult()
955  if self._seedPrinter:
956  self._seedPrinter.setIndentFrom(self, adjust=1)
957  ret.extend(self._seedPrinter.diff(track1.seed(), track2.seed(), self._diffForTwiki))
958  self._seedPrinter.restoreIndent()
959  return ret
960 
961  def printTrack(self, track):
962  lst = self.printHeader(track)
963  lst.extend(self.printHits(track))
964  lst.extend(self.printSeed(track))
965  return lst
966 
968  return self._trackingParticleMatchPrinter.printMatchedTrackingParticles(self._prefix, track)
969 
971  lst = []
972  lst.extend(self.printTrack(track))
973  lst.extend(self.printMatchedTrackingParticles(track))
974  return lst
975 
976  def __call__(self, track, out=sys.stdout):
977  if isinstance(out, list):
978  lst = out
979  else:
980  lst = []
981 
982  lst.extend(self.printTrackAndMatchedTrackingParticles(track))
983 
984  if not isinstance(out, list):
985  for line in lst:
986  out.write(line)
987  out.write("\n")
988 
989  def diff(self, track1, track2, diffTrackingParticles=True):
990  if track1 is None:
991  lst = self.printTrack(track2) + self.printMatchedTrackingParticles(track2)
992  return _makediff([], lst)
993  if track2 is None:
994  lst = self.printTrack(track1) + self.printMatchedTrackingParticles(track1)
995  return _makediff(lst, [])
996 
997  ret = _DiffResult()
998  ret.extend(_mapdiff(self.printHeader, track1, track2))
999  if self._diffForTwiki:
1000  trk1TPs = [tpInfo.trackingParticle() for tpInfo in track1.matchedTrackingParticleInfos()]
1001  trk2TPs = [tpInfo.trackingParticle() for tpInfo in track2.matchedTrackingParticleInfos()]
1002 
1003  pt_pull1 = "None"
1004  pt_pull2 = "None"
1005  dxy_pull1 = "None"
1006  dxy_pull2 = "None"
1007  dz_pull1 = "None"
1008  dz_pull2 = "None"
1009 
1010  ptPull1 = track1.ptPull()
1011  ptPull2 = track2.ptPull()
1012  if ptPull1 is not None and ptPull2 is not None:
1013  fmt = "{pull:.3g}"
1014  pt_pull1 = fmt.format(pull=ptPull1)
1015  pt_pull2 = fmt.format(pull=ptPull2)
1016  dxy_pull1 = fmt.format(pull=track1.dxyPull())
1017  dxy_pull2 = fmt.format(pull=track2.dxyPull())
1018  dz_pull1 = fmt.format(pull=track1.dzPull())
1019  dz_pull2 = fmt.format(pull=track2.dzPull())
1020 
1021  lst = [
1022  self._prefix+" parameters",
1023  self._prefix+" pt %RED%{pt1:.3g}%ENDCOLOR% %GREEN%{pt2:.3g}%ENDCOLOR%".format(pt1=track1.pt(), pt2=track2.pt()),
1024  ]
1025  if pt_pull1 != "None":
1026  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=pt_pull1, pull2=pt_pull2))
1027  lst.extend([
1028  self._prefix+" eta %RED%{eta1:.3g}%ENDCOLOR% %GREEN%{eta2:.3g}%ENDCOLOR%".format(eta1=track1.eta(), eta2=track2.eta()),
1029  self._prefix+" phi %RED%{phi1:.3g}%ENDCOLOR% %GREEN%{phi2:.3g}%ENDCOLOR%".format(phi1=track1.phi(), phi2=track2.phi()),
1030  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()),
1031  ])
1032  if dxy_pull1 != "None":
1033  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=dxy_pull1, pull2=dxy_pull2))
1034  lst.extend([
1035  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()),
1036  ])
1037  if dz_pull1 != "None":
1038  lst.append(self._prefix+" pull %RED%{pull1}%ENDCOLOR% %GREEN%{pull2}%ENDCOLOR%".format(pull1=dz_pull1, pull2=dz_pull2))
1039  lst.extend([
1040  self._prefix+" chi2/ndof %RED%{chi1:.3g}%ENDCOLOR% %GREEN%{chi2:.3g}%ENDCOLOR%".format(chi1=track1.nChi2(), chi2=track2.nChi2()),
1041  ])
1042  ret.extend(_makediff(lst, lst, equalPrefix="?"))
1043 
1044  diffHits = _mapdiff(self.printHits, track1, track2)
1045  ret.extend(diffHits)
1046  if self._hits and self._diffForTwiki:
1047  ret.extend(_formatHitDiffForTwiki(diffHits, self._prefix))
1048 
1049  ret.extend(self.diffSeeds(track1, track2))
1050  if diffTrackingParticles:
1051  ret.extend(_mapdiff(self.printMatchedTrackingParticles, track1, track2))
1052  return ret
1053 
1055  def __init__(self, indent=0, parentage=True, hits=True, tracks=True, trackPrinter=None, bestMatchingTrack=True, seedPrinter=SeedPrinter()):
1056  super(TrackingParticlePrinter, self).__init__(indent)
1057  self._parentage = parentage
1058  self._hits = hits
1059  self._tracks = tracks
1060  self._trackPrinter = trackPrinter
1061  self._bestMatchingTrack = bestMatchingTrack
1062  self._seedPrinter = seedPrinter
1063 
1064  def _printTP(self, tp):
1065  genIds = ""
1066  if len(tp.genPdgIds()) > 0:
1067  genIds = " genPdgIds "+",".join([str(pdgId) for pdgId in tp.genPdgIds()])
1068  fromB = ""
1069  if tp.isFromBHadron():
1070  fromB = " from B hadron"
1071  return [
1072  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()),
1073  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())
1074  ]
1075 
1076 
1077  def _parentageChain(self, tp):
1078  lst = []
1079  prodVtx = tp.parentVertex()
1080  if prodVtx.nSourceTrackingParticles() == 1:
1081  lst.extend(self._printTP(next(prodVtx.sourceTrackingParticles())))
1082  elif prodVtx.nSourceTrackingParticles() >= 2:
1083  self.indent(1)
1084  for tp in prodVtx.sourceTrackingParticles():
1085  self._printTP(tp, out)
1086  self.indent(1)
1087  lst.extend(self._parentageChain(tp))
1088  self.indent(-1)
1089  self.indent(-1)
1090  return lst
1091 
1092  def printTrackingParticle(self, tp):
1093  lst = []
1094  lst.extend(self._printTP(tp))
1095  if self._parentage:
1096  if tp.parentVertex().nSourceTrackingParticles() > 0:
1097  lst.append(self._prefix+" parentage chain")
1098  self.indent(2)
1099  lst.extend(self._parentageChain(tp))
1100  self.indent(-2)
1101  return lst
1102 
1103  def printHits(self, tp):
1104  lst = []
1105  if self._hits:
1106  lst.append(self._prefix+" sim hits"+_hitPatternSummary(tp.simHits()))
1107  for simhit in tp.simHits():
1108  tmp = []
1109  for h in simhit.hits():
1110  tmp.append(",".join([str(trk.index()) for trk in h.tracks()]) + ":%d"%h.index())
1111  if len(tmp) == 0:
1112  matched = "not matched to any Track/RecHit"
1113  else:
1114  matched = "matched to Tracks:RecHits "+";".join(tmp)
1115 
1116  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))
1117  return lst
1118 
1120  return [self._prefix+" matched to tracks"]
1121 
1122  def _printMatchedTracks(self, tracks, header=None, useTrackPrinter=True):
1123  lst = []
1124  if header is not None:
1125  lst.append(self._prefix+" "+header)
1126  else:
1127  lst.extend(self._printMatchedTracksHeader())
1128  if self._trackPrinter is None or not useTrackPrinter:
1129  lst[-1] += " "+",".join([str(track.index()) for track in tracks])
1130  else:
1131  self._trackPrinter.indent(2)
1132  for track in tracks:
1133  lst.extend(self._trackPrinter.printTrack(track))
1134  self._trackPrinter.restoreIndent()
1135  return lst
1136 
1137  def printMatchedTracks(self, tp, useTrackPrinter=True):
1138  lst = []
1139  if tp.nMatchedTracks() == 0:
1140  header = "not matched to any track"
1141  lst.append(self._prefix+" "+header)
1142  if self._bestMatchingTrack:
1143  bestTrack = tp.bestMatchingTrack()
1144  if bestTrack is not None:
1145  lst.pop()
1146  lst.extend(self._printMatchedTracks([bestTrack], header+", but a following track with >= 3 matched hits is found", useTrackPrinter=useTrackPrinter))
1147  else:
1148  lst.extend(self._printMatchedTracks([trkInfo.track() for trkInfo in tp.matchedTrackInfos()], useTrackPrinter=useTrackPrinter))
1149  return lst
1150 
1151  def diffMatchedTracks(self, tp1, tp2):
1152  ntrk1 = tp1.nMatchedTracks()
1153  ntrk2 = tp2.nMatchedTracks()
1154 
1155  if ntrk1 == 0 or ntrk2 == 0 or self._trackPrinter is None:
1156  return _makediff(self.printMatchedTracks(tp1), self.printMatchedTracks(tp2))
1157 
1158  self._trackPrinter.indent(2)
1159 
1161  trks1 = [trkInfo1.track() for trkInfo1 in tp1.matchedTrackInfos()]
1162  trks2 = [trkInfo2.track() for trkInfo2 in tp2.matchedTrackInfos()]
1163  #for trkInfo1 in tp1.matchedTrackInfos():
1164  # trk1 = trkInfo1.track()
1165  # matchedTrk2 = _matchTracksByHits(trk1, trks2)
1166  #
1167  # if matchedTrk2 is None: # no more tracks in tp2
1168  # diff.extend(_makediff(self._trackPrinter.printTrack(trk1), []))
1169  # else: # diff trk1 to best-matching track from tp2
1170  # trks2.remove(matchedTrk2)
1171  # diff.extend(self._trackPrinter.diff(trk1, matchedTrk2))
1172  #
1173  #for trk2 in trks2: # remaining tracks in tp2
1174  # diff.extend(_makediff([], self._trackPrinter.printTrack(trk2)))
1175  diff.extend(diffTrackListsFromSameTrackingParticle(self._trackPrinter, trks1, trks2))
1176 
1177  self._trackPrinter.restoreIndent()
1178  return diff
1179 
1181  return [self._prefix+ " not matched to any seed"]
1182 
1184  return [self._prefix+" matched to seeds"]
1185 
1186  def printMatchedSeeds(self, tp):
1187  lst = []
1188  if self._seedPrinter:
1189  if tp.nMatchedSeeds() == 0:
1190  lst.extend(self._printMatchedSeeds0())
1191  else:
1192  lst.extend(self._printMatchedSeedsHeader())
1193  self._seedPrinter.setIndentFrom(self, adjust=2)
1194  for seedInfo in tp.matchedSeedInfos():
1195  lst.extend(self._seedPrinter.printSeed(seedInfo.seed()))
1196  self._seedPrinter.restoreIndent()
1197  return lst
1198 
1199  def diffMatchedSeeds(self, tp1, tp2):
1200  if not self._seedPrinter:
1201  return []
1202 
1203  nseed1 = tp1.nMatchedSeeds()
1204  nseed2 = tp2.nMatchedSeeds()
1205  if nseed1 == 0 or nseed2 == 0:
1206  return _makediff(self.printMatchedSeeds(tp1), self.printMatchedSeeds(tp2))
1207 
1208  self._seedPrinter.setIndentFrom(self, adjust=2)
1209 
1211  seeds2 = [seedInfo2.seed() for seedInfo2 in tp2.matchedSeedInfos()]
1212  for seedInfo1 in tp1.matchedSeedInfos():
1213  seed1 = seedInfo1.seed()
1214  matchedSeed2 = _matchTracksByHits(seed1, seeds2)[0]
1215 
1216  if matchedSeed2 is None: # no more seeds in tp2
1217  diff.extend(_makediff(self._seedPrinter.printSeed(seed1), []))
1218  else: # diff seed1 to best-matching seed from tp2
1219  seeds2.remove(matchedSeed2)
1220  diff.extend(_makediff(self._seedPrinter.printSeed(seed1), self._seedPrinter.printSeed(matchedSeed2)))
1221 
1222  for seed2 in seeds2: # remiaining seeds in tp2
1223  diff.extend(_makediff([], self._seedPrinter.printSeed(seed2)))
1224 
1225  self._seedPrinter.restoreIndent()
1226 
1227  return diff
1228 
1229  def __call__(self, tp, out=sys.stdout):
1230  if isinstance(out, list):
1231  lst = out
1232  else:
1233  lst = []
1234 
1235  lst.extend(self.printTrackingParticle(tp))
1236  lst.extend(self.printHits(tp))
1237  lst.extend(self.printMatchedTracks(tp))
1238  lst.extend(self.printMatchedSeeds(tp))
1239 
1240  for line in lst:
1241  out.write(line)
1242  out.write("\n")
1243 
1244  def diff(self, tp1, tp2):
1245  ret = _DiffResult()
1246  ret.extend(_mapdiff(self.printTrackingParticle, tp1, tp2))
1247  ret.extend(_mapdiff(self.printHits, tp1, tp2))
1248  ret.extend(self.diffMatchedTracks(tp1, tp2))
1249  ret.extend(self.diffMatchedSeeds(tp1, tp2))
1250  return ret
1251 
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)