CMS 3D CMS Logo

ntupleDataFormat.py
Go to the documentation of this file.
1 import math
2 import collections
3 
4 import ROOT
5 
8 
10  """Adaptor class representing a collection of objects.
11 
12  Concrete collection classes should inherit from this class.
13 
14  """
15  def __init__(self, tree, sizeBranch, objclass):
16  """Constructor.
17 
18  Arguments:
19  tree -- TTree object
20  sizeBranch -- Name of the branch to be used in size()
21  objclass -- Class to be used for the objects in __getitem__()
22  """
23  super(_Collection, self).__init__()
24  self._tree = tree
25  self._sizeBranch = sizeBranch
26  self._objclass = objclass
27 
28  def size(self):
29  """Number of objects in the collection."""
30  return int(getattr(self._tree, self._sizeBranch).size())
31 
32  def __len__(self):
33  """Number of objects in the collection."""
34  return self.size()
35 
36  def __getitem__(self, index):
37  """Get object 'index' in the collection."""
38  return self._objclass(self._tree, index)
39 
40  def __iter__(self):
41  """Returns generator for the objects."""
42  for index in xrange(self.size()):
43  yield self._objclass(self._tree, index)
44 
45 class _Object(object):
46  """Adaptor class representing a single object in a collection.
47 
48  The member variables of the object are obtained from the branches
49  with common prefix and a given index.
50 
51  Concrete object classes should inherit from this class.
52  """
53  def __init__(self, tree, index, prefix):
54  """Constructor.
55 
56  Arguments:
57  tree -- TTree object
58  index -- Index for this object
59  prefix -- Prefix of the branchs
60  """
61  super(_Object, self).__init__()
62  self._tree = tree
63  self._index = index
64  self._prefix = prefix
65 
66  def __getattr__(self, attr):
67  """Return object member variable.
68 
69  'attr' is translated as a branch in the TTree (<prefix>_<attr>).
70  """
71  self._checkIsValid()
72  val = getattr(self._tree, self._prefix+"_"+attr)[self._index]
73  return lambda: val
74 
75  def _checkIsValid(self):
76  """Raise an exception if the object index is not valid."""
77  if not self.isValid():
78  raise Exception("%s is not valid" % self.__class__.__name__)
79 
80  def isValid(self):
81  """Check if object index is valid."""
82  return self._index != -1
83 
84  def index(self):
85  """Return object index."""
86  return self._index
87 
89  """Adaptor class for objects containgin DetId (hits)."""
90  def __init__(self):
91  super(_DetIdStrAdaptor, self).__init__()
92 
93  def layerStr(self):
94  """Returns a string describing the layer of the hit."""
95  self._checkIsValid()
96  get = lambda name: getattr(self._tree, self._prefix+"_"+name)[self._index]
97  subdet = get("subdet")
98  side = ""
99  isPhase2OTBarrel = (subdet == SubDet.TOB and hasattr(self._tree, self._prefix+"_isLower"))
100  if subdet in [SubDet.FPix, SubDet.TID, SubDet.TEC] or isPhase2OTBarrel:
101  sideNum = get("side")
102  if sideNum == 1:
103  side = "-"
104  elif sideNum == 2:
105  side = "+"
106  elif isPhase2OTBarrel and sideNum == 3:
107  side = ""
108  else:
109  side = "?"
110  return "%s%d%s" % (SubDet.toString(subdet),
111  getattr(self._tree, self._prefix+"_layer")[self._index],
112  side)
113 
114  def detIdStr(self):
115  """Returns a string describing the DetId fields."""
116  self._checkIsValid
117  get = lambda name: getattr(self._tree, self._prefix+"_"+name)[self._index]
118  isPhase2 = hasattr(self._tree, self._prefix+"_isLower")
119  def stereo():
120  if isPhase2:
121  if get("isLower"):
122  return " isLower"
123  if get("isUpper"):
124  return " isUpper"
125  if get("isStack"):
126  return " isStack"
127  else:
128  if get("isStereo"):
129  return " isStereo"
130  if get("isRPhi"):
131  return " isRPhi"
132  if get("isGlued"):
133  return " isGlued"
134  return ""
135 
136  subdet = get("subdet")
137  if subdet == SubDet.BPix:
138  return "ladder {} module {}".format(get("ladder"), get("module"))
139  if subdet == SubDet.FPix:
140  return "blade {} panel {} module {}".format(get("blade"), get("panel"), get("module"))
141  if subdet == SubDet.TIB:
142  return "side {} order {} string {} module {}{}".format(get("side"), get("order"), get("string"), get("module"), stereo())
143  if subdet == SubDet.TID:
144  return "ring {} order {} module {}{}".format(get("ring"), get("order"), get("module"), stereo())
145  if subdet == SubDet.TOB:
146  if isPhase2:
147  return "rod {} module {}{}".format(get("rod"), get("module"), stereo())
148  else:
149  return "side {} rod {} module {}{}".format(get("side"), get("rod"), get("module"), stereo())
150  if subdet == SubDet.TEC:
151  return "order {} petal {} ring {} module {}{}".format(get("order"), get("petalNumber"), get("ring"), get("module"), stereo())
152  raise Exception("Unknown subdet %d" % subdet)
153 
155  """Adaptor class for pixel/strip hit objects."""
156  def __init__(self, tree, index, prefix):
157  """Constructor.
158 
159  Arguments:
160  tree -- TTree object
161  index -- Index for this object
162  prefix -- Prefix of the branchs
163  """
164  """Constructor
165  """
166  super(_HitObject, self).__init__(tree, index, prefix)
167 
168  def ntracks(self):
169  """Returns number of tracks containing this hit."""
170  self._checkIsValid()
171  return getattr(self._tree, self._prefix+"_trkIdx")[self._index].size()
172 
173  def tracks(self):
174  """Returns generator for tracks containing this hit.
175 
176  The generator returns Track objects
177  """
178  self._checkIsValid()
179  for itrack in getattr(self._tree, self._prefix+"_trkIdx")[self._index]:
180  yield Track(self._tree, itrack)
181 
182  def nseeds(self):
183  """Returns number of seeds containing this hit."""
184  self._checkIsValid()
185  return getattr(self._tree, self._prefix+"_seeIdx")[self._index].size()
186 
187  def seeds(self):
188  """Returns generator for tracks containing this hit.
189 
190  The generator returns Seed objects
191  """
192  self._checkIsValid()
193  for iseed in getattr(self._tree, self._prefix+"_seeIdx")[self._index]:
194  yield Seed(self._tree, iseed)
195 
196  def r(self):
197  return math.sqrt(self.x()**2 + self.y()**2)
198 
199  def r3D(self):
200  return math.sqrt(self.x()**2 + self.y()**2 + self.z()**2)
201 
203  """Adaptor class for objects containing hits (e.g. tracks)"""
204  def __init__(self):
205  super(_RecoHitAdaptor, self).__init__()
206 
207  def _hits(self):
208  """Internal method to generate pairs of hit index and type."""
209  for ihit, hitType in zip(self.hitIdx(), self.hitType()):
210  yield (ihit, hitType)
211 
212  def hits(self):
213  """Returns generator for hits.
214 
215  Generator returns PixelHit/StripHit/GluedHit/Phase2OT depending on the
216  hit type.
217 
218  """
219  for ihit, hitType in self._hits():
220  if hitType == 0:
221  yield PixelHit(self._tree, ihit)
222  elif hitType == 1:
223  yield StripHit(self._tree, ihit)
224  elif hitType == 2:
225  yield GluedHit(self._tree, ihit)
226  elif hitType == 3:
227  yield InvalidHit(self._tree, ihit)
228  elif hitType == 4:
229  yield Phase2OTHit(self._tree, ihit)
230  else:
231  raise Exception("Unknown hit type %d" % hitType)
232 
233  def pixelHits(self):
234  """Returns generator for pixel hits."""
235  self._checkIsValid()
236  for ihit, hitType in self._hits():
237  if hitType != 0:
238  continue
239  yield PixelHit(self._tree, ihit)
240 
241  def stripHits(self):
242  """Returns generator for strip hits."""
243  self._checkIsValid()
244  for ihit, hitType in self._hits():
245  if hitType != 1:
246  continue
247  yield StripHit(self._tree, ihit)
248 
249  def gluedHits(self):
250  """Returns generator for matched strip hits."""
251  self._checkIsValid()
252  for ihit, hitType in self._hits():
253  if hitType != 2:
254  continue
255  yield GluedHit(self._tree, ihit)
256 
257  def invalidHits(self):
258  """Returns generator for invalid hits."""
259  self._checkIsValid()
260  for ihit, hitType in self._hits():
261  if hitType != 3:
262  continue
263  yield InvalidHit(self._tree, ihit)
264 
265  def phase2OTHits(self):
266  """Returns generator for phase2 outer tracker hits."""
267  self._checkIsValid()
268  for ihit, hitType in self._hits():
269  if hitType != 4:
270  continue
271  yield Phase2OTHit(self._tree, ihit)
272 
274  """Adaptor class for objects containing or matched to SimHits (e.g. reco hits)."""
275  def __init__(self):
276  super(_SimHitMatchAdaptor, self).__init__()
277 
278  def _nMatchedSimHits(self):
279  """Internal method to get the number of matched SimHits."""
280  return getattr(self._tree, self._prefix+"_simHitIdx")[self._index].size()
281 
282  def nMatchedSimHits(self):
283  """Returns the number of matched SimHits."""
284  self._checkIsValid()
285  return self._nMatchedSimHits()
286 
288  """Returns a generator for matched SimHits.
289 
290  The generator returns SimHitMatchInfo objects.
291  """
292  self._checkIsValid()
293  for imatch in xrange(self._nMatchedSimHits()):
294  yield SimHitMatchInfo(self._tree, self._index, imatch, self._prefix)
295 
297  """Adaptor class for objects matched to TrackingParticles."""
298  def __init__(self):
299  super(_TrackingParticleMatchAdaptor, self).__init__()
300 
302  """Internal method to get the number of matched TrackingParticles."""
303  return getattr(self._tree, self._prefix+"_simTrkIdx")[self._index].size()
304 
306  """Returns the number of matched TrackingParticles."""
307  self._checkIsValid()
308  return self._nMatchedTrackingParticles()
309 
311  """Returns a generator for matched TrackingParticles.
312 
313  The generator returns TrackingParticleMatchInfo objects.
314 
315  """
316  self._checkIsValid()
317  for imatch in xrange(self._nMatchedTrackingParticles()):
318  yield TrackingParticleMatchInfo(self._tree, self._index, imatch, self._prefix)
319 
321  """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle.
322 
323  Best-matching is defined as the one with largest number of
324  hits matched to the hits of a track (>= 3). If there are many
325  fulfilling the same number of hits, the one inducing the
326  innermost hit of the track is chosen.
327  """
328  idx = self.bestSimTrkIdx()
329  if idx < 0:
330  return None
331  return TrackingParticle(self._tree, idx)
332 
334  """Fraction of shared hits with reco hits as denominator for best-matching TrackingParticle."""
335  return self.bestSimTrkShareFrac()
336 
338  """Fraction of shared hits with TrackingParticle::numberOfTrackerHits() as denominator for best-matching TrackingParticle."""
339  return self.bestSimTrkShareFracSimDenom()
340 
342  """Fraction of shared hits with number of reco clusters associated to a TrackingParticle as denominator for best-matching TrackingParticle."""
343  return self.bestSimTrkShareFracSimClusterDenom()
344 
346  """Normalized chi2 calculated from track parameters+covariance matrix and TrackingParticle parameters for best-matching TrackingParticle."""
347  return self.bestSimTrkNChi2()
348 
350  """Returns best-matching TrackingParticle, even for fake tracks, or None if there is no best-matching TrackingParticle.
351 
352  Best-matching is defined as the one with largest number of
353  hits matched to the hits of a track (>= 3) starting from the
354  beginning of the track. If there are many fulfilling the same
355  number of hits, "a first TP" is chosen (a bit arbitrary, but
356  should be rare".
357  """
358  idx = self.bestFromFirstHitSimTrkIdx()
359  if idx < 0:
360  return None
361  return TrackingParticle(self._tree, idx)
362 
364  """Fraction of shared hits with reco hits as denominator for best-matching TrackingParticle starting from the first hit of a track."""
365  return self.bestFromFirstHitSimTrkShareFrac()
366 
368  """Fraction of shared hits with TrackingParticle::numberOfTrackerHits() as denominator for best-matching TrackingParticle starting from the first hit of a track."""
369  return self.bestFromFirstHitSimTrkShareFracSimDenom()
370 
372  """Fraction of shared hits with number of reco clusters associated to a TrackingParticle as denominator for best-matching TrackingParticle starting from the first hit of a track."""
373  return self.bestFromFirstHitSimTrkShareFracSimClusterDenom()
374 
376  """Normalized chi2 calculated from track parameters+covariance matrix and TrackingParticle parameters for best-matching TrackingParticle starting from the first hit of a track."""
377  return self.bestFromFirstHitSimTrkNChi2()
378 
379 ##########
381  """Class abstracting the whole ntuple/TTree.
382 
383  Main benefit is to provide nice interface for
384  - iterating over events
385  - querying whether hit/seed information exists
386 
387  Note that to iteratate over the evets with zip(), you should use
388  itertools.izip() instead.
389  """
390  def __init__(self, fileName, tree="trackingNtuple/tree"):
391  """Constructor.
392 
393  Arguments:
394  fileName -- String for path to the ROOT file
395  tree -- Name of the TTree object inside the ROOT file (default: 'trackingNtuple/tree')
396  """
397  super(TrackingNtuple, self).__init__()
398  self._file = ROOT.TFile.Open(fileName)
399  self._tree = self._file.Get(tree)
400  self._entries = self._tree.GetEntriesFast()
401 
402  def file(self):
403  return self._file
404 
405  def tree(self):
406  return self._tree
407 
408  def nevents(self):
409  return self._entries
410 
411  def hasHits(self):
412  """Returns true if the ntuple has hit information."""
413  return hasattr(self._tree, "pix_isBarrel")
414 
415  def hasSeeds(self):
416  """Returns true if the ntuple has seed information."""
417  return hasattr(self._tree, "see_fitok")
418 
419  def __iter__(self):
420  """Returns generator for iterating over TTree entries (events)
421 
422  Generator returns Event objects.
423 
424  """
425  for jentry in xrange(self._entries):
426  # get the next tree in the chain and verify
427  ientry = self._tree.LoadTree( jentry )
428  if ientry < 0: break
429  # copy next entry into memory and verify
430  nb = self._tree.GetEntry( jentry )
431  if nb <= 0: continue
432 
433  yield Event(self._tree, jentry)
434 
435  def getEvent(self, index):
436  """Returns Event for a given index"""
437  ientry = self._tree.LoadTree(index)
438  if ientry < 0: return None
439  nb = self._tree.GetEntry(ientry) # ientry or jentry?
440  if nb <= 0: None
441 
442  return Event(self._tree, ientry) # ientry of jentry?
443 
444 ##########
445 class Event(object):
446  """Class abstracting a single event.
447 
448  Main benefit is to provide nice interface to get various objects
449  or collections of objects.
450  """
451  def __init__(self, tree, entry):
452  """Constructor.
453 
454  Arguments:
455  tree -- TTree object
456  entry -- Entry number in the tree
457  """
458  super(Event, self).__init__()
459  self._tree = tree
460  self._entry = entry
461 
462  def entry(self):
463  return self._entry
464 
465  def event(self):
466  """Returns event number."""
467  return self._tree.event
468 
469  def lumi(self):
470  """Returns lumisection number."""
471  return self._tree.lumi
472 
473  def run(self):
474  """Returns run number."""
475  return self._tree.run
476 
477  def eventId(self):
478  """Returns (run, lumi, event) tuple."""
479  return (self._tree.run, self._tree.lumi, self._tree.event)
480 
481  def eventIdStr(self):
482  """Returns 'run:lumi:event' string."""
483  return "%d:%d:%d" % self.eventId()
484 
485  def beamspot(self):
486  """Returns BeamSpot object."""
487  return BeamSpot(self._tree)
488 
489  def tracks(self):
490  """Returns Tracks object."""
491  return Tracks(self._tree)
492 
493  def pixelHits(self):
494  """Returns PixelHits object."""
495  return PixelHits(self._tree)
496 
497  def stripHits(self):
498  """Returns StripHits object."""
499  return StripHits(self._tree)
500 
501  def gluedHits(self):
502  """Returns GluedHits object."""
503  return GluedHits(self._tree)
504 
505  def phase2OTHits(self):
506  """Returns Phase2OTHits object."""
507  return Phase2OTHits(self._tree)
508 
509  def seeds(self):
510  """Returns Seeds object."""
511  return Seeds(self._tree)
512 
513  def trackingParticles(self):
514  """Returns TrackingParticles object."""
515  return TrackingParticles(self._tree)
516 
517  def vertices(self):
518  """Returns Vertices object."""
519  return Vertices(self._tree)
520 
521  def trackingVertices(self):
522  """Returns TrackingVertices object."""
523  return TrackingVertices(self._tree)
524 
525 ##########
527  """Class representing the beam spot."""
528  def __init__(self, tree):
529  """Constructor.
530 
531  Arguments:
532  tree -- TTree object
533  """
534  super(BeamSpot, self).__init__()
535  self._tree = tree
536  self._prefix = "bsp"
537 
538  def __getattr__(self, attr):
539  """Return object member variable.
540 
541  'attr' is translated as a branch in the TTree (bsp_<attr>).
542  """
543  val = getattr(self._tree, self._prefix+"_"+attr)
544  return lambda: val
545 
546 ##########
548  """Class representing a match to a SimHit.
549 
550  The point of this class is to provide, in addition to the matched
551  SimHit, also other information about the match (e.g. fraction of
552  charge from this SimHit).
553  """
554  def __init__(self, tree, index, shindex, prefix):
555  """Constructor.
556 
557  Arguments:
558  tree -- TTree object
559  index -- Index of the hit matched to SimHit
560  shindex -- Index of the SimHit match (second index in _simHitIdx branch)
561  prefix -- String for prefix of the object (track/seed/hit) matched to TrackingParticle
562  """
563  super(SimHitMatchInfo, self).__init__(tree, index, prefix)
564  self._shindex = shindex
565 
566  def __getattr__(self, attr):
567  """Custom __getattr__ because of the second index needed to access the branch."""
568  val = super(SimHitMatchInfo, self).__getattr__(attr)()[self._shindex]
569  return lambda: val
570 
571  def simHit(self):
572  """Returns matched SimHit."""
573  self._checkIsValid()
574  return SimHit(self._tree, getattr(self._tree, self._prefix+"_simHitIdx")[self._index][self._shindex])
575 
577 
578  """Class representing a match to a TrackingParticle.
579 
580  The point of this class is to provide, in addition to the matched
581  TrackingParticle, also other information about the match (e.g.
582  shared hit fraction for tracks/seeds).
583  """
584  def __init__(self, tree, index, tpindex, prefix):
585  """Constructor.
586 
587  Arguments:
588  tree -- TTree object
589  index -- Index of the object (track/seed) matched to TrackingParticle
590  tpindex -- Index of the TrackingParticle match (second index in _simTrkIdx branch)
591  prefix -- String for prefix of the object (track/seed) matched to TrackingParticle
592  """
593  super(TrackingParticleMatchInfo, self).__init__(tree, index, prefix)
594  self._tpindex = tpindex
595 
596  def __getattr__(self, attr):
597  """Custom __getattr__ because of the second index needed to access the branch.
598 
599  Note that when mapping the 'attr' to a branch, a 'simTrk' is
600  prepended and the first letter of 'attr' is turned to upper
601  case.
602  """
603  val = super(TrackingParticleMatchInfo, self).__getattr__("simTrk"+attr[0].upper()+attr[1:])()[self._tpindex]
604  return lambda: val
605 
606  def trackingParticle(self):
607  """Returns matched TrackingParticle."""
608  return TrackingParticle(self._tree, self.idx())
609 
611  """Class representing a match to a Track.
612 
613  The point of this class is to provide, in addition to the matched
614  Track, also other information about the match (e.g. shared hit fraction.
615  """
616  def __init__(self, tree, index, trkindex, prefix):
617  """Constructor.
618 
619  Arguments:
620  tree -- TTree object
621  index -- Index of the object (TrackingParticle) matched to track
622  trkindex -- Index of the track match (second index in _trkIdx branch)
623  prefix -- String for prefix of the object (TrackingParticle) matched to track
624  """
625  super(TrackMatchInfo, self).__init__(tree, index, prefix)
626  self._trkindex = trkindex
627 
628  def __getattr__(self, attr):
629  """Custom __getattr__ because of the second index needed to access the branch.
630 
631  Note that when mapping the 'attr' to a branch, a 'trk' is
632  prepended and the first letter of 'attr' is turned to upper
633  case.
634  """
635  val = super(TrackMatchInfo, self).__getattr__("trk"+attr[0].upper()+attr[1:])()[self._trkindex]
636  return lambda: val
637 
638  def track(self):
639  """Returns matched Track."""
640  return Track(self._tree, self.idx())
641 
643  """Class representing a match to a Seed.
644 
645  The point of this class is to provide an interface compatible with
646  all other "MatchInfo" classes
647 
648  """
649  def __init__(self, tree, index, seedindex, prefix):
650  """Constructor.
651 
652  Arguments:
653  tree -- TTree object
654  index -- Index of the object (TrackingParticle) matched to seed
655  seedindex -- Index of the seed match (second index in _trkIdx branch)
656  prefix -- String for prefix of the object (TrackingParticle) matched to seed
657  """
658  super(SeedMatchInfo, self).__init__(tree, index, prefix)
659  self._seedindex = seedindex
660 
661  def seed(self):
662  """Returns matched Seed."""
663  self._checkIsValid()
664  return Seed(self._tree, getattr(self._tree, self._prefix+"_seedIdx")[self._index][self._seedindex])
665 
666 ##########
668  """Class presenting a track."""
669  def __init__(self, tree, index):
670  """Constructor.
671 
672  Arguments:
673  tree -- TTree object
674  index -- Index of the track
675  """
676  super(Track, self).__init__(tree, index, "trk")
677 
678  def seed(self):
679  """Returns Seed of the track."""
680  self._checkIsValid()
681  return Seed(self._tree, self._tree.trk_seedIdx[self._index])
682 
683  def vertex(self):
684  """Returns Vertex that used this track in its fit."""
685  self._checkIsValid()
686  return Vertex(self._tree, self._tree.trk_vtxIdx[self._index])
687 
688  def ptPull(self):
689  tp = self.bestMatchingTrackingParticle()
690  if tp is None:
691  return None
692  return (self.pt() - tp.pca_pt())/self.ptErr()
693 
694  def thetaPull(self):
695  tp = self.bestMatchingTrackingParticle()
696  if tp is None:
697  return None
698  return (getattr(self, "lambda")() - tp.pca_lambda())/self.lambdaErr() # as in MTV
699 
700  def phiPull(self):
701  tp = self.bestMatchingTrackingParticle()
702  if tp is None:
703  return None
704  return (self.phi() - tp.pca_phi())/self.phiErr()
705 
706  def dxyPull(self):
707  tp = self.bestMatchingTrackingParticle()
708  if tp is None:
709  return None
710  return (self.dxy() - tp.pca_dxy())/self.dxyErr()
711 
712  def dzPull(self):
713  tp = self.bestMatchingTrackingParticle()
714  if tp is None:
715  return None
716  return (self.dz() - tp.pca_dz())/self.dzErr()
717 
719  """Class presenting a collection of tracks."""
720  def __init__(self, tree):
721  """Constructor.
722 
723  Arguments:
724  tree -- TTree object
725  """
726  super(Tracks, self).__init__(tree, "trk_pt", Track)
727 
728 ##########
730  """Class representing a pixel hit."""
731  def __init__(self, tree, index):
732  """Constructor.
733 
734  Arguments:
735  tree -- TTree object
736  index -- Index of the hit
737  """
738  super(PixelHit, self).__init__(tree, index, "pix")
739 
740  def isValidHit(self):
741  return True
742 
744  """Class presenting a collection of pixel hits."""
745  def __init__(self, tree):
746  """Constructor.
747 
748  Arguments:
749  tree -- TTree object
750  """
751  super(PixelHits, self).__init__(tree, "pix_isBarrel", PixelHit)
752 
753 ##########
755  """Class representing a strip hit."""
756  def __init__(self, tree, index):
757  """Constructor.
758 
759  Arguments:
760  tree -- TTree object
761  index -- Index of the hit
762  """
763  super(StripHit, self).__init__(tree, index, "str")
764 
765  def isValidHit(self):
766  return True
767 
769  """Class presenting a collection of strip hits."""
770  def __init__(self, tree):
771  """Constructor.
772 
773  Arguments:
774  tree -- TTree object
775  """
776  super(StripHits, self).__init__(tree, "str_isBarrel", StripHit)
777 
778 ##########
780  """Class representing a matched strip hit."""
781  def __init__(self, tree, index):
782  """Constructor.
783 
784  Arguments:
785  tree -- TTree object
786  index -- Index of the hit
787  """
788  super(GluedHit, self).__init__(tree, index, "glu")
789 
790  def isValidHit(self):
791  return True
792 
793  def monoHit(self):
794  """Returns a StripHit for the mono hit."""
795  self._checkIsValid()
796  return StripHit(self._tree, self._tree.glu_monoIdx[self._index])
797 
798  def stereoHit(self):
799  """Returns a StripHit for the stereo hit."""
800  self._checkIsValid()
801  return StripHit(self._tree, self._tree.glu_stereoIdx[self._index])
802 
803  def nseeds(self):
804  """Returns the number of seeds containing this hit."""
805  self._checkIsValid()
806  return self._tree.glu_seeIdx[self._index].size()
807 
808  def seeds(self):
809  """Returns generator for seeds containing this hit.
810 
811  The generator returns Seed objects
812  """
813  self._checkIsValid()
814  for iseed in self._tree.glu_seeIdx[self._index]:
815  yield Seed(self._tree, iseed)
816 
818  """Class presenting a collection of matched strip hits."""
819  def __init__(self, tree):
820  """Constructor.
821 
822  Arguments:
823  tree -- TTree object
824  """
825  super(GluedHits, self).__init__(tree, "glu_isBarrel", GluedHit)
826 
827 ##########
829  # repeating TrackingRecHit::Type
830  Type = _Enum(
831  missing = 1,
832  inactive = 2,
833  bad = 3,
834  missing_inner = 4,
835  missing_outer = 5
836  )
837 
838  """Class representing an invalid hit."""
839  def __init__(self, tree, index):
840  """Constructor.
841 
842  Arguments:
843  tree -- TTree object
844  index -- Index of the hit
845  """
846  super(InvalidHit, self).__init__(tree, index, "inv")
847 
848  def isValidHit(self):
849  return False
850 
851  def layerStr(self):
852  """Returns a string describing the layer of the hit."""
853  invalid_type = self._tree.inv_type[self._index]
854  return super(InvalidHit, self).layerStr() + " (%s)"%InvalidHit.Type.toString(invalid_type)
855 
856 ##########
858  """Class representing a phase2 OT hit."""
859  def __init__(self, tree, index):
860  """Constructor.
861 
862  Arguments:
863  tree -- TTree object
864  index -- Index of the hit
865  """
866  super(Phase2OTHit, self).__init__(tree, index, "ph2")
867 
868  def isValidHit(self):
869  return True
870 
872  """Class presenting a collection of phase2 OT hits."""
873  def __init__(self, tree):
874  """Constructor.
875 
876  Arguments:
877  tree -- TTree object
878  """
879  super(Phase2OTHits, self).__init__(tree, "ph2_isBarrel", Phase2OTHit)
880 
881 ##########
882 def _seedOffsetForAlgo(tree, algo):
883  """Internal function for returning a pair of indices for the beginning of seeds of a given 'algo', and the one-beyond-last index of the seeds."""
884  for ioffset, offset in enumerate(tree.see_offset):
885  if tree.see_algo[offset] == algo:
886  next_offset = tree.see_offset[ioffset+1] if ioffset < tree.see_offset.size()-1 else tree.see_algo.size()
887  return (offset, next_offset)
888  return (-1, -1)
889 
891  """Class presenting a seed."""
892  def __init__(self, tree, index):
893  """Constructor.
894 
895  Arguments:
896  tree -- TTree object
897  index -- Index of the seed
898  """
899  super(Seed, self).__init__(tree, index, "see")
900 
901  def indexWithinAlgo(self):
902  """Returns the seed index within the seeds of the same algo.
903 
904  In case of errors, -1 is returned.
905  """
906  self._checkIsValid()
907  algo = self._tree.see_algo[self._index]
908  (offset, next_offset) = _seedOffsetForAlgo(self._tree, algo)
909  if offset == -1: # algo not found
910  return -1
911  return self._index - offset
912 
913  def track(self):
914  """Returns Track that was made from this seed."""
915  self._checkIsValid()
916  return Track(self._tree, self._tree.see_trkIdx[self._index])
917 
919  """Class presenting a collection of seeds."""
920  def __init__(self, tree):
921  """Constructor.
922 
923  Arguments:
924  tree -- TTree object
925  """
926  super(Seeds, self).__init__(tree, "see_pt", Seed)
927 
928  def nSeedsForAlgo(self, algo):
929  """Returns the number of seeds for a given 'algo'."""
930  (offset, next_offset) = _seedOffsetForAlgo(self._tree, algo)
931  return next_offset - offset
932 
933  def seedsForAlgo(self, algo):
934  """Returns generator iterating over the seeds of a given 'algo'.
935 
936  Generator returns Seed object.
937  """
938  (offset, next_offset) = _seedOffsetForAlgo(self._tree, algo)
939  for isee in xrange(offset, next_offset):
940  yield Seed(self._tree, isee)
941 
942  def seedForAlgo(self, algo, iseed):
943  """Returns Seed of index 'iseed' for 'algo'."""
944  (offset, next_offset) = _seedOffsetForAlgo(self._tree, algo)
945  if iseed >= (next_offset-offset):
946  raise Exception("Seed index %d is larger than the number of seeds %d for algo %d (%s)" % (iseed, next_offset-offset, algo, Algo.toString(algo)))
947  return Seed(self._tree, offset+iseed)
948 
949 ##########
951  """Class representing a SimHit which has not induced a RecHit."""
952  def __init__(self, tree, index):
953  """Constructor.
954 
955  Arguments:
956  tree -- TTree object
957  index -- Index of the SimHit
958  """
959  super(SimHit, self).__init__(tree, index, "simhit")
960 
961  def nRecHits(self):
962  self._checkIsValid()
963  return self._tree.simhit_hitIdx[self._index].size()
964 
965  def trackingParticle(self):
966  self._checkIsValid()
967  return TrackingParticle(self._tree, getattr(self._tree, self._prefix+"_simTrkIdx")[self._index])
968 
969 ##########
971  """Class representing a TrackingParticle."""
972  def __init__(self, tree, index):
973  """Constructor.
974 
975  Arguments:
976  tree -- TTree object
977  index -- Index of the TrackingParticle
978  """
979  super(TrackingParticle, self).__init__(tree, index, "sim")
980 
981  def _nMatchedTracks(self):
982  """Internal function to get the number of matched tracks."""
983  return self._tree.sim_trkIdx[self._index].size()
984 
985  def nMatchedTracks(self):
986  """Returns the number of matched tracks."""
987  self._checkIsValid()
988  return self._nMatchedTracks()
989 
990  def matchedTrackInfos(self):
991  """Returns a generator for matched tracks.
992 
993  The generator returns TrackMatchInfo objects.
994  """
995  self._checkIsValid()
996  for imatch in xrange(self._nMatchedTracks()):
997  yield TrackMatchInfo(self._tree, self._index, imatch, self._prefix)
998 
999  def bestMatchingTrack(self):
1000  """Returns best-matching track, even for non-reconstructed TrackingParticles, or None, if there is no best-matching track.
1001 
1002  Best-matching is defined as the one with largest number of
1003  hits matched to the hits of a TrackingParticle (>= 3). If
1004  there are many fulfilling the same number of hits, the one
1005  inducing the innermost hit of the TrackingParticle is chosen.
1006  """
1007  self._checkIsValid()
1008  if self._nMatchedTracks() == 1:
1009  return next(self.matchedTrackInfos()).track()
1010 
1011  tracks = collections.OrderedDict()
1012  for hit in self.simHits():
1013  for recHit in hit.hits():
1014  for track in recHit.tracks():
1015  if track.index() in tracks:
1016  tracks[track.index()] += 1
1017  else:
1018  tracks[track.index()] = 1
1019 
1020  best = (None, 2)
1021  for trackIndex, nhits in tracks.iteritems():
1022  if nhits > best[1]:
1023  best = (trackIndex, nhits)
1024  if best[0] is None:
1025  return None
1026  return Tracks(self._tree)[best[0]]
1027 
1028  def _nMatchedSeeds(self):
1029  """Internal function to get the number of matched seeds."""
1030  return self._tree.sim_seedIdx[self._index].size()
1031 
1032  def nMatchedSeeds(self):
1033  """Returns the number of matched seeds."""
1034  self._checkIsValid()
1035  return self._nMatchedSeeds()
1036 
1037  def matchedSeedInfos(self):
1038  """Returns a generator for matched tracks.
1039 
1040  The generator returns SeedMatchInfo objects.
1041  """
1042  self._checkIsValid()
1043  for imatch in xrange(self._nMatchedSeeds()):
1044  yield SeedMatchInfo(self._tree, self._index, imatch, self._prefix)
1045 
1046  def nSimHits(self):
1047  self._checkIsValid()
1048  return self.simHitIdx().size()
1049 
1050  def simHits(self):
1051  """Returns generator for SimHits."""
1052  self._checkIsValid()
1053  for ihit in self.simHitIdx():
1054  yield SimHit(self._tree, ihit)
1055 
1056  def parentVertex(self):
1057  """Returns the parent TrackingVertex."""
1058  self._checkIsValid()
1059  return TrackingVertex(self._tree, self._tree.sim_parentVtxIdx[self._index])
1060 
1061  def decayVertices(self):
1062  """Returns a generator for decay vertices.
1063 
1064  The generator returns TrackingVertex objects.
1065  """
1066  self._checkIsValid()
1067  for ivtx in self._tree.sim_decayVtxIdx[self._index]:
1068  yield TrackingVertex(self._tree, ivtx)
1069 
1070  def isLooper(self):
1071  """Returns True if this TrackingParticle is a looper.
1072 
1073  Note that the check involves looping over the SimHits, so it is not too cheap."""
1074  self._checkIsValid()
1075  prevr = 0
1076  for ihit in self.simHitIdx():
1077  hit = SimHit(self._tree, ihit)
1078  r = hit.x()**2 + hit.y()**2
1079  if r < prevr:
1080  return True
1081  prevr = r
1082  return False
1083 
1084 
1086  """Class presenting a collection of TrackingParticles."""
1087  def __init__(self, tree):
1088  """Constructor.
1089 
1090  Arguments:
1091  tree -- TTree object
1092  """
1093  super(TrackingParticles, self).__init__(tree, "sim_pt", TrackingParticle)
1094 
1095 ##########
1097  """Class presenting a primary vertex."""
1098  def __init__(self, tree, index):
1099  """Constructor.
1100 
1101  Arguments:
1102  tree -- TTree object
1103  index -- Index of the vertex
1104  """
1105  super(Vertex, self).__init__(tree, index, "vtx")
1106 
1107  def nTracks(self):
1108  """Returns the number of tracks used in the vertex fit."""
1109  self._checkIsValid()
1110  return self._tree.vtx_trkIdx[self._index].size()
1111 
1112  def tracks(self):
1113  """Returns a generator for the tracks used in the vertex fit.
1114 
1115  The generator returns Track object.
1116  """
1117  self._checkIsValid()
1118  for itrk in self._tree.vtx_trkIdx[self._index]:
1119  yield Track(self._tree, itrk)
1120 
1122  """Class presenting a collection of vertices."""
1123  def __init__(self, tree):
1124  """Constructor.
1125 
1126  Arguments:
1127  tree -- TTree object
1128  """
1129  super(Vertices, self).__init__(tree, "vtx_valid", Vertex)
1130 
1131 ##########
1133  """Class representing a TrackingVertex."""
1134  def __init__(self, tree, index):
1135  """Constructor.
1136 
1137  Arguments:
1138  tree -- TTree object
1139  index -- Index of the TrackingVertex
1140  """
1141  super(TrackingVertex, self).__init__(tree, index, "simvtx")
1142 
1144  """Returns the number of source TrackingParticles."""
1145  self._checkIsValid()
1146  return self._tree.simvtx_sourceSimIdx[self._index].size()
1147 
1149  """Returns the number of daughter TrackingParticles."""
1150  self._checkIsValid()
1151  return self._tree.simvtx_daughterSimIdx[self._index].size()
1152 
1154  """Returns a generator for the source TrackingParticles."""
1155  self._checkIsValid()
1156  for isim in self._tree.simvtx_sourceSimIdx[self._index]:
1157  yield TrackingParticle(self._tree, isim)
1158 
1160  """Returns a generator for the daughter TrackingParticles."""
1161  self._checkIsValid()
1162  for isim in self._tree.simvtx_daughterSimIdx[self._index]:
1163  yield TrackingParticle(self._tree, isim)
1164 
1166  """Class presenting a collection of TrackingVertices."""
1167  def __init__(self, tree):
1168  """Constructor.
1169 
1170  Arguments:
1171  tree -- TTree object
1172  """
1173  super(TrackingVertex, self).__init__(tree, "simvtx_x")
size
Write out results.
def __init__(self, tree, index, trkindex, prefix)
def __init__(self, tree, index)
def __init__(self, tree, index)
def __init__(self, tree)
def __init__(self, fileName, tree="trackingNtuple/tree")
def seedsForAlgo(self, algo)
def __init__(self, tree, index)
def __init__(self, tree, index, shindex, prefix)
def __init__(self, tree, entry)
def __init__(self, tree, index)
def __init__(self, tree, index, seedindex, prefix)
def seedForAlgo(self, algo, iseed)
def __init__(self, tree, index, tpindex, prefix)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def __init__(self, tree, index)
def __init__(self, tree, index)
def __init__(self, tree, index)
def nSeedsForAlgo(self, algo)
def __init__(self, tree, index, prefix)
def __getattr__(self, attr)
def __init__(self, tree, index, prefix)
def __init__(self, tree, sizeBranch, objclass)
def __init__(self, tree, index)
def __init__(self, tree, index)
def __init__(self, tree, index)
def _seedOffsetForAlgo(tree, algo)
T get(const Candidate &c)
Definition: component.h:55