Belle II Software  release-08-01-10
attributemaps.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 
4 
11 
12 from ROOT import gSystem
13 
14 from ROOT import Belle2 # make Belle2 namespace available
15 
16 import bisect
17 import colorsys
18 
19 gSystem.Load('libframework') # for PyStoreArray
20 gSystem.Load('libcdc') # for CDCSimHit
21 gSystem.Load('libtracking') # for CDCWire and so on
22 gSystem.Load('libgenfit2') # for GFTrackCands
23 gSystem.Load('libdataobjects')
24 # Standard color map for id types
25 listColors = [ # 'magenta',
26  # 'gold',
27  # 'yellow',
28  # 'aquamarine',
29  'red',
30  'blue',
31  'green',
32  'orange',
33  'cyan',
34  'olive',
35  'lime',
36  'maroon',
37  'tomato',
38  'turquoise',
39  'mediumspringgreen',
40  'darkgreen',
41  'indigo',
42 ]
43 
44 
45 def timeOfFlightToColor(timeOfFlight):
46  """
47  Translates the given floating point time of flight to a color.
48  """
49 
50  # values are all fractions of their respective scale
51 
52  # Full color circle in 3 nanoseconds
53  hue = 360 / 3.0 * timeOfFlight % 360.0 / 360.0
54  saturation = 0.75
55  lightness = 0.5
56 
57  (red, green, blue) = colorsys.hls_to_rgb(hue, lightness, saturation)
58 
59  color = 'rgb({0:.2%}, {1:.2%}, {2:.2%})'.format(red, green, blue)
60  return color
61 
62 
63 def inTrackIdToColor(inTrackId):
64  """
65  Translates the given integer in track id to a color.
66  """
67 
68  hue = 50 * inTrackId % 360 / 360.0
69  saturation = 0.75
70  lightness = 0.5
71 
72  (red, green, blue) = colorsys.hls_to_rgb(hue, lightness, saturation)
73 
74  color = 'rgb({0:.2%}, {1:.2%}, {2:.2%})'.format(red, green, blue)
75  return color
76 
77 
79 
80  """
81  Base class for CDCHit to the stroke width map functional objects.
82  """
83 
84  def __call__(self, iCDCHit, cdcHit):
85  """
86  Function call to map the CDCHit id and object to a stroke width.
87  """
88 
89  return 0.2
90 
91 
93 
94  """
95  CDCHit to stroke width map highlighting the CDCHits with 0 drift length.
96  """
97 
98  def __call__(self, iCDCHit, cdcHit):
99  """
100  Function call to map the CDCHit id and object to a stroke width.
101  """
102 
103  wirehit = Belle2.TrackFindingCDC.CDCWireHit(cdcHit)
104  if wirehit.getRefDriftLength() == 0.0:
105  return 1
106  else:
107  return 0.2
108 
109 
111 
112  """
113  Base class for CDCHit to color map functional objects.
114  """
115 
116 
117  bkgHitColor = 'orange'
118 
119  def __call__(self, iCDCHit, cdcHit):
120  """
121  Function call to map the CDCHit id and object to a color.
122  """
123 
124  return self.bkgHitColorbkgHitColor
125 
126 
128 
129  """
130  CDCHit to color map highlighting the CDCHits with 0 drift length.
131  """
132 
133  def __call__(self, iCDCHit, cdcHit):
134  """
135  Function call to map the CDCHit id and object to a color.
136  """
137 
138  wirehit = Belle2.TrackFindingCDC.CDCWireHit(cdcHit)
139  if wirehit.getRefDriftLength() == 0.0:
140  return 'red'
141  else:
142  return self.bkgHitColorbkgHitColor
143 
144 
146 
147  """
148  CDCHit to color map highlighting the CDCHits that posses the do not use flag.
149  """
150 
151  def __init__(self):
152  """Constructor"""
153  super().__init__()
154 
155  self.storedWireHitsstoredWireHits = Belle2.PyStoreObj('CDCWireHitVector')
156  if not self.storedWireHitsstoredWireHits:
157  print('Could not find CDCWireHitVector in the data store to lookup TakenFlag')
158 
159  def __call__(self, iCDCHit, cdcHit):
160  """
161  Function call to map the CDCHit id and object to a color.
162  """
163  if not self.storedWireHitsstoredWireHits:
164  return self.bkgHitColorbkgHitColor
165 
166  wireHits = self.storedWireHitsstoredWireHits.obj().get()
167  # Search the sorted range of wire hits for the one corresponding to the given CDCHit
168  wireHit = wireHits.at(bisect.bisect_left(wireHits, cdcHit))
169  if wireHit.getAutomatonCell().hasTakenFlag():
170  return 'red'
171  else:
172  return self.bkgHitColorbkgHitColor
173 
174 
176 
177  """
178  CDCHit to color map by their local right left passage information from Monte Carlo truth
179  """
180 
181  def __call__(self, iCDCHit, cdcHit):
182  """
183  Function call to map the CDCHit id and object to a color.
184  """
185 
187  rlInfo = mcHitLookUp.getRLInfo(cdcHit)
188  if rlInfo == 1:
189  # Right
190  return 'green'
191  elif rlInfo == -1 or rlInfo == 65535: # <- The root interface mistakes the signed enum value for an unsigned value
192  # Left
193  return 'red'
194  else:
195  self.bkgHitColorbkgHitColor
196 
197  def __str__(self):
198  """
199  Informal string summarizing the translation from right left passage variable to colors.
200  """
201 
202  return 'Local right left passage variable: green <-> right, red <-> left, orange <-> not determinable.'
203 
204 
206 
207  """
208  CDCRecoHit3D to color map for the correctness of the rl information
209  """
210 
211  def __init__(self):
212  """Constructor"""
214  mcHitLookUp.fill()
215 
216  def __call__(self, iCDCRecoHit, cdcRecoHit3D):
217  """
218  This function maps the cdcRecoHit3D to the color which inidcated the correctness of the rl passage
219  """
220 
221  cdcHit = cdcRecoHit3D.getWireHit().getHit()
222 
224  rlInfo = mcHitLookUp.getRLInfo(cdcHit)
225 
226  if rlInfo == -32768 or rlInfo == 32768: # <- The root interface mistakes the signed enum value for an unsigned value
227  return 'violet'
228  elif rlInfo == cdcRecoHit3D.getRLInfo():
229  return 'green'
230  else:
231  return 'red'
232 
233  def __str__(self):
234  """
235  Informal string summarizing the translation from right left passage variable to colors.
236  """
237  return 'Correct RL info: gree, wrong RL info: red'
238 
239 
241 
242  """
243  CDCHit to color map by their assoziated CDCSimHit::getPosFlag property.
244  """
245 
246  def __call__(self, iCDCHit, cdcHit):
247  """
248  Function call to map the CDCHit id and object to a color.
249  """
250 
251  simHit = cdcHit.getRelated('CDCSimHits')
252  posFlag = simHit.getPosFlag()
253  if posFlag == 0:
254  # Right
255  return 'green'
256  elif posFlag == 1:
257  # Left
258  return 'red'
259  else:
260  self.bkgHitColorbkgHitColor
261 
262  def __str__(self):
263  """
264  Informal string summarizing the translation from CDCSimHit::getPosFlag variable to colors.
265  """
266 
267  return 'PosFlag variable of the related CDCSimHit: green <-> 0 (Right), red <-> 1 (Left), orange <-> determinable.'
268 
269 
271 
272  """
273  CDCHit to color map by their assoziated CDCSimHit::getBackgroundTag property.
274  """
275 
276 
277  BackgroundMetaData = Belle2.BackgroundMetaData
278 
279 
280  bkgname_by_bkgtag = {
281  BackgroundMetaData.bg_none: 'bg_none',
282  BackgroundMetaData.bg_Coulomb_LER: 'bg_Coulomb_LER',
283  BackgroundMetaData.bg_Coulomb_HER: 'bg_Coulomb_HER',
284  BackgroundMetaData.bg_RBB_LER: 'bg_RBB_LER',
285  BackgroundMetaData.bg_RBB_HER: 'bg_RBB_HER',
286  BackgroundMetaData.bg_Touschek_LER: 'bg_Touschek_LER',
287  BackgroundMetaData.bg_Touschek_HER: 'bg_Touschek_HER',
288  BackgroundMetaData.bg_twoPhoton: 'bg_twoPhoton',
289  BackgroundMetaData.bg_RBB_gamma: 'bg_RBB_gamma',
290  BackgroundMetaData.bg_RBB_LER_far: 'bg_RBB_LER_far',
291  BackgroundMetaData.bg_RBB_HER_far: 'bg_RBB_HER_far',
292  BackgroundMetaData.bg_Touschek_LER_far: 'bg_Touschek_LER_far',
293  BackgroundMetaData.bg_Touschek_HER_far: 'bg_Touschek_HER_far',
294  BackgroundMetaData.bg_SynchRad_LER: 'bg_SynchRad_LER',
295  BackgroundMetaData.bg_SynchRad_HER: 'bg_SynchRad_HER',
296  BackgroundMetaData.bg_other: 'bg_other',
297  }
298 
299 
300  color_by_bkgtag = {
301  BackgroundMetaData.bg_none: 'orange',
302  BackgroundMetaData.bg_Coulomb_LER: 'red',
303  BackgroundMetaData.bg_Coulomb_HER: 'darkred',
304  BackgroundMetaData.bg_RBB_LER: 'blue',
305  BackgroundMetaData.bg_RBB_HER: 'darkblue',
306  BackgroundMetaData.bg_Touschek_LER: 'green',
307  BackgroundMetaData.bg_Touschek_HER: 'darkgreen',
308  BackgroundMetaData.bg_twoPhoton: 'violet',
309  BackgroundMetaData.bg_RBB_gamma: 'skyblue',
310  BackgroundMetaData.bg_RBB_LER_far: 'turquoise',
311  BackgroundMetaData.bg_RBB_HER_far: 'darkturquoise',
312  BackgroundMetaData.bg_Touschek_LER_far: 'olivergreen',
313  BackgroundMetaData.bg_Touschek_HER_far: 'darkolivegreen',
314  BackgroundMetaData.bg_SynchRad_LER: 'goldenrod',
315  BackgroundMetaData.bg_SynchRad_HER: 'darkgoldenrod',
316  BackgroundMetaData.bg_other: 'orange',
317  }
318 
319  def __call__(self, iCDCHit, cdcHit):
320  """
321  Function call to map the CDCHit id and object to a color.
322  """
323 
324  cdcSimHit = cdcHit.getRelated('CDCSimHits')
325  backgroundTag = cdcSimHit.getBackgroundTag()
326 
327  color = self.color_by_bkgtagcolor_by_bkgtag.get(backgroundTag, None)
328 
329  if color is None:
330  print('Background tag %s not associated with a color.'
331  % backgroundTag)
332  return 'orange'
333  else:
334  return color
335 
336  def __str__(self):
337  """
338  Informal string summarizing the translation from CDCSimHit::getBackgroundTag variable to colors.
339  """
340 
341  color_by_bkgname = {}
342 
343  for backgroundTag in self.bkgname_by_bkgtagbkgname_by_bkgtag:
344  name = self.bkgname_by_bkgtagbkgname_by_bkgtag[backgroundTag]
345  color = self.color_by_bkgtagcolor_by_bkgtag[backgroundTag]
346  color_by_bkgname[name] = color
347 
348  bkgname_and_color = sorted(color_by_bkgname.items())
349 
350  message = 'Background tag color coding is \n%s' % '\n'.join(name + ' -> ' + color for (name, color) in bkgname_and_color)
351  return message
352 
353 
355 
356  """
357  CDCHit to color map by their Monte Carlo segment id
358  """
359 
360  def __call__(self, iCDCHit, cdcHit):
361  """
362  Function call to map the CDCHit id and object to a color.
363  """
364 
366  inTrackSegmentId = mcHitLookUp.getInTrackSegmentId(cdcHit)
367 
368  if inTrackSegmentId < 0:
369  return self.bkgHitColorbkgHitColor
370  else:
371  # values are all fractions of their respective scale
372  hue = 50 * inTrackSegmentId % 360 / 360.0
373  saturation = 0.75
374  lightness = 0.5
375 
376  (red, green, blue) = colorsys.hls_to_rgb(hue, lightness,
377  saturation)
378 
379  color = 'rgb({0:.2%}, {1:.2%}, {2:.2%})'.format(red, green, blue)
380  return color
381 
382 
384 
385  """
386  CDCHit to color map by their assoziated CDCSimHit::getFlightTime.
387  """
388 
389  def __call__(self, iCDCHit, cdcHit):
390  """
391  Function call to map the CDCHit id and object to a color.
392  """
393 
394  simHit = cdcHit.getRelated('CDCSimHits')
395  timeOfFlight = simHit.getFlightTime()
396 
397  return timeOfFlightToColor(timeOfFlight)
398 
399 
401 
402  """
403  CDCHit to color map indicating the reassignment to a different MCParticle.
404  """
405 
406  def __call__(self, iCDCHit, cdcHit):
407  """
408  Function call to map the CDCHit id and object to a color.
409  """
410 
411  relatedMCParticles = cdcHit.getRelationsWith('MCParticles')
412  if relatedMCParticles.size() == 0:
413  return self.bkgHitColorbkgHitColor
414  else:
415  mcRelationWeight = relatedMCParticles.weight(0)
416  if mcRelationWeight > 0:
417  return 'green'
418  else:
419  return 'red'
420 
421 
423 
424  """
425  CDCHit to color map coloring by the assoziated MCParticle::getArrayIndex()
426  """
427 
428  def __init__(self):
429  """
430  Construction method setting up a Monte Carlo id to color dictionary which is continously filled
431  as new during the event.
432  """
433 
434 
435  self.color_by_mcparticleIdcolor_by_mcparticleId = {-1: self.bkgHitColorbkgHitColor}
436 
437  def __call__(self, iCDCHit, cdcHit):
438  """
439  Function call to map the CDCHit id and object to a color.
440  """
441 
442  mcParticle = cdcHit.getRelated('MCParticles')
443  if mcParticle:
444  mcParticleId = mcParticle.getArrayIndex()
445  else:
446  mcParticleId = -1
447 
448  # cdcSimHit = cdcHit.getRelated("CDCSimHits")
449  # if cdcSimHit:
450  # cdcSimHitTrackId = cdcSimHit.getTrackId()
451  # else:
452  # cdcSimHitTrackId = -1
453 
454  if mcParticleId in self.color_by_mcparticleIdcolor_by_mcparticleId:
455  color = self.color_by_mcparticleIdcolor_by_mcparticleId[mcParticleId]
456  else:
457  iColor = len(self.color_by_mcparticleIdcolor_by_mcparticleId)
458  iColor = iColor % len(listColors)
459  color = listColors[iColor]
460  self.color_by_mcparticleIdcolor_by_mcparticleId[mcParticleId] = color
461 
462  return color
463 
464 
466 
467  """
468  CDCHit to color map by the assoziated MCParticle::getPDG()
469  """
470 
471 
472  color_by_pdgcode = {
473  -999: CDCHitColorMap.bkgHitColor,
474  11: 'blue',
475  -11: 'blue',
476  13: 'turquoise',
477  -13: 'turquoise',
478  15: 'cyan',
479  -15: 'cyan',
480  211: 'green',
481  -211: 'green',
482  321: 'olive',
483  -321: 'olive',
484  2212: 'red',
485  -2212: 'red',
486  }
487 
488 
489  missing_pdg_color = 'lime'
490 
491  def __call__(self, iCDCHit, cdcHit):
492  """
493  Function call to map the CDCHit id and object to a color.
494  """
495 
496  mcParticle = cdcHit.getRelated('MCParticles')
497  if mcParticle:
498  pdgcode = mcParticle.getPDG()
499  else:
500 
501  # getSecondaryPhysicsProcess()
502  pdgcode = -999
503 
504  if pdgcode in self.color_by_pdgcodecolor_by_pdgcode:
505  color = self.color_by_pdgcodecolor_by_pdgcode[pdgcode]
506  else:
507  print('Unknown PDG code', pdgcode)
508  color = self.missing_pdg_colormissing_pdg_color
509 
510  return color
511 
512  def __str__(self):
513  """
514  Informal string summarizing the translation from pdg codes to colors.
515  """
516 
517  legend_head = 'Legend:\n'
518 
519  pdg_code_by_color = {}
520 
521  for (pdgcode, color) in list(self.color_by_pdgcodecolor_by_pdgcode.items()):
522  pdg_code_by_color.setdefault(color, [])
523  pdg_code_by_color[color].append(pdgcode)
524 
525  legend_content = '\n'.join(str(color) + '->' + str(pdg_code_by_color[color])
526  for color in pdg_code_by_color)
527 
528  return legend_head + legend_content
529 
530 
532 
533  """
534  CDCHit to color map by the isPrimary information as well as the secondary process type in case the particle is not primary.
535  """
536 
537  def __init__(self):
538  """
539  Constuction method setting up a dictionary to count the hits for each secondary type.
540  """
541 
542 
543  self.n_hits_by_secondary_typen_hits_by_secondary_type = {}
544 
545  def __call__(self, iCDCHit, cdcHit):
546  """
547  Function call to map the CDCHit id and object to a color.
548  """
549 
550  mcParticle = cdcHit.getRelated('MCParticles')
551  if mcParticle:
552  primaryFlag = 1
553  isPrimary = mcParticle.hasStatus(primaryFlag)
554  secondaryProcess = mcParticle.getSecondaryPhysicsProcess()
555  if secondaryProcess > 0:
556  motherMCParticle = mcParticle.getMother()
557  secondary_type = (motherMCParticle.getPDG(),
558  mcParticle.getPDG())
559  else:
560  motherMCParticle = None
561  secondary_type = (-999, mcParticle.getPDG())
562 
563  self.n_hits_by_secondary_typen_hits_by_secondary_type.setdefault(secondary_type, 0)
564  self.n_hits_by_secondary_typen_hits_by_secondary_type[secondary_type] = \
565  self.n_hits_by_secondary_typen_hits_by_secondary_type[secondary_type] + 1
566  if isPrimary:
567  return 'blue'
568  elif secondaryProcess > 200:
569  # decay in flight
570  return 'green'
571  else:
572  return 'red'
573  else:
574  return self.bkgHitColorbkgHitColor
575 
576  def __str__(self):
577  """
578  Informal string summarizing the translation from seconday process codes to colors.
579  """
580 
581  return """
582 Legend:
583 blue->primary
584 green->secondary decay in flight
585 red->secondary other process
586 orange->beam background
587 """ \
588  + str(self.n_hits_by_secondary_typen_hits_by_secondary_type)
589 
590 
592 
593  """
594  Base class for Segments to color map functional objects.
595  """
596 
597 
598  bkgSegmentColor = 'orange'
599 
600  def __call__(self, iSegment, segment):
601  """
602  Function call to map a segments object from the local finder to a color.
603  """
604 
605  return self.bkgSegmentColorbkgSegmentColor
606 
607 
609 
610  """
611  Segment to color map based on the matched MCTrackId
612  """
613 
614  def __call__(self, iSegment, segment):
615  """
616  Function call to map a segments object from the local finder to a color.
617  """
618 
619  mcSegmentLookUp = \
621 
622  mcTrackId = mcSegmentLookUp.getMCTrackId(segment)
623  if mcTrackId < 0:
624  return self.bkgSegmentColorbkgSegmentColor
625  else:
626  iColor = mcTrackId % len(listColors)
627  color = listColors[iColor]
628  return color
629 
630 
632 
633  """
634  Segment to color map based on the forward or backward alignment relative to the match Monte Carlo track.
635  """
636 
637  def __call__(self, iSegment, segment):
638  """
639  Function call to map a segments object from the local finder to a color.
640  """
641 
642  mcSegmentLookUp = \
644 
645  # Just to look at matched segments
646  mcTrackId = mcSegmentLookUp.getMCTrackId(segment)
647  if mcTrackId < 0:
648  return self.bkgSegmentColorbkgSegmentColor
649 
650  fbInfo = mcSegmentLookUp.isForwardOrBackwardToMCTrack(segment)
651  if fbInfo == 1:
652  return 'green'
653  elif fbInfo == -1 or fbInfo == 65535: # <- The root interface mistakes the signed enum value for an unsigned value
654  return 'red'
655  else:
656  print('Segment not orientable to match track')
657  return self.bkgSegmentColorbkgSegmentColor
658 
659 
661 
662  """
663  Segment to color map by the in track id of the first hit.
664  """
665 
666  def __call__(self, iSegment, segment):
667  """
668  Function call to map a segments object from the local finder to a color.
669  """
670 
671  mcSegmentLookUp = \
673 
674  # Just to look at matched segments
675  firstInTrackId = mcSegmentLookUp.getFirstInTrackId(segment)
676 
677  if firstInTrackId < 0:
678  return self.bkgSegmentColorbkgSegmentColor
679 
680  return inTrackIdToColor(firstInTrackId)
681 
682 
684 
685  """
686  Segment to color map by the in track id of the last hit.
687  """
688 
689  def __call__(self, iSegment, segment):
690  """
691  Function call to map a segments object from the local finder to a color.
692  """
693 
694  mcSegmentLookUp = \
696 
697  # Just to look at matched segments
698  lastInTrackId = mcSegmentLookUp.getLastInTrackId(segment)
699 
700  if lastInTrackId < 0:
701  return self.bkgSegmentColorbkgSegmentColor
702 
703  return inTrackIdToColor(lastInTrackId)
704 
705 
707 
708  """
709  Segment to color map by the number of passed superlayers of the first hit.
710  """
711 
712  def __call__(self, iSegment, segment):
713  """
714  Function call to map a segments object from the local finder to a color.
715  """
716 
717  mcSegmentLookUp = \
719 
720  # Just to look at matched segments
721  firstNPassedSuperLayers = \
722  mcSegmentLookUp.getFirstNPassedSuperLayers(segment)
723 
724  if firstNPassedSuperLayers < 0:
725  return self.bkgSegmentColorbkgSegmentColor
726 
727  return inTrackIdToColor(firstNPassedSuperLayers)
728 
729 
731 
732  """
733  Segment to color map by the number of passed superlayers of the last hit.
734  """
735 
736  def __call__(self, iSegment, segment):
737  """
738  Function call to map a segments object from the local finder to a color.
739  """
740 
741  mcSegmentLookUp = \
743 
744  # Just to look at matched segments
745  lastNPassedSuperLayers = \
746  mcSegmentLookUp.getLastNPassedSuperLayers(segment)
747 
748  if lastNPassedSuperLayers < 0:
749  return self.bkgSegmentColorbkgSegmentColor
750 
751  return inTrackIdToColor(lastNPassedSuperLayers)
Metadata information about the beam background file.
a (simplified) python wrapper for StoreObjPtr.
Definition: PyStoreObj.h:67
static const CDCMCHitLookUp & getInstance()
Getter for the singletone instance.
static const CDCMCSegment2DLookUp & getInstance()
Getter for the singletone instance.
Class representing a hit wire in the central drift chamber.
Definition: CDCWireHit.h:55
dictionary color_by_pdgcode
Dictionary to define the color for the most relevant.
string missing_pdg_color
Color for the case a particle a pdg code not mentioned in the color_by_pdgcode map.
color_by_mcparticleId
Dictionary mapping the MCParticle ids to colors for consistent and contious use of the available colo...
n_hits_by_secondary_type
Dictionary keeping track of the number of hits with a specific secondary process type.