11from collections import defaultdict , namedtuple
2+ from xml .sax .saxutils import escape
23
34import numpy as np
45import scipy .sparse as sp
@@ -565,6 +566,27 @@ def _get_color_column(self):
565566 int_col [color_column >= thresh ] = i
566567 return int_col
567568
569+ def _tooltip (self , colors , distribution ):
570+ if self .attr_color .is_discrete :
571+ values = self .attr_color .values
572+ else :
573+ values = self ._bin_names ()
574+ tot = np .sum (distribution )
575+ nbhp = "\N{NON-BREAKING HYPHEN} "
576+ return '<table style="white-space: nowrap">' + "" .join (f"""
577+ <tr>
578+ <td>
579+ <font color={ color .name ()} >■</font>
580+ <b>{ escape (val ).replace ("-" , nbhp )} </b>:
581+ </td>
582+ <td>
583+ { n } ({ n / tot * 100 :.1f} %)
584+ </td>
585+ </tr>"""
586+ for color , val , n in zip (colors ,values , distribution )
587+ if n ) \
588+ + "</table>"
589+
568590 def _draw_pie_charts (self , sizes ):
569591 fx , fy = self ._grid_factors
570592 color_column = self ._get_color_column ()
@@ -573,12 +595,14 @@ def _draw_pie_charts(self, sizes):
573595 for x in range (self .size_x - self .hexagonal * (y % 2 )):
574596 r = sizes [x , y ]
575597 if not r :
598+ self .grid_cells [y , x ].setToolTip ("" )
576599 continue
577600 members = self .get_member_indices (x , y )
578601 color_dist = np .bincount (color_column [members ],
579602 minlength = len (colors ))
580- color_dist = color_dist .astype (float ) / len (members )
581- pie = PieChart (color_dist , r / 2 , colors )
603+ rel_color_dist = color_dist .astype (float ) / len (members )
604+ pie = PieChart (rel_color_dist , r / 2 , colors )
605+ pie .setToolTip (self ._tooltip (colors , color_dist ))
582606 self .elements .addToGroup (pie )
583607 pie .setPos (x + (y % 2 ) * fx , y * fy )
584608
@@ -604,6 +628,7 @@ def _draw_colored_circles(self, sizes):
604628 ellipse .setRect (x + (y % 2 ) * fx - r / 2 , y * fy - r / 2 , r , r )
605629 ellipse .setPen (pen )
606630 ellipse .setBrush (brush )
631+ ellipse .setToolTip (self ._tooltip (self .colors , bc ))
607632 self .elements .addToGroup (ellipse )
608633
609634 def redraw_grid (self ):
@@ -806,12 +831,7 @@ def create_legend(self):
806831 if self .attr_color .is_discrete :
807832 names = self .attr_color .values
808833 else :
809- sval = self .attr_color .repr_val
810- names = \
811- [f"< { sval (self .thresholds [0 ])} " ] \
812- + [f"{ sval (x )} - { sval (y )} "
813- for x , y in zip (self .thresholds , self .thresholds [1 :])] \
814- + [f"≥ { sval (self .thresholds [- 1 ])} " ]
834+ names = self ._bin_names ()
815835
816836 items = []
817837 size = 8
@@ -833,6 +853,14 @@ def create_legend(self):
833853 self .scene .addItem (self .legend )
834854 self .set_legend_pos ()
835855
856+ def _bin_names (self ):
857+ sval = self .attr_color .repr_val
858+ return \
859+ [f"< { sval (self .thresholds [0 ])} " ] \
860+ + [f"{ sval (x )} - { sval (y )} "
861+ for x , y in zip (self .thresholds , self .thresholds [1 :])] \
862+ + [f"≥ { sval (self .thresholds [- 1 ])} " ]
863+
836864 def set_legend_pos (self ):
837865 if self .legend is None :
838866 return
0 commit comments