11from collections import defaultdict , namedtuple
2+ from xml .sax .saxutils import escape
23
34import numpy as np
45import scipy .sparse as sp
@@ -570,6 +571,26 @@ def _get_color_column(self):
570571 int_col [color_column >= thresh ] = i
571572 return int_col
572573
574+ def _tooltip (self , colors , distribution ):
575+ if self .attr_color .is_discrete :
576+ values = self .attr_color .values
577+ else :
578+ values = self ._bin_names ()
579+ tot = np .sum (distribution )
580+ nbhp = "\N{NON-BREAKING HYPHEN} "
581+ return '<table style="white-space: nowrap">' + "" .join (f"""
582+ <tr>
583+ <td>
584+ <font color={ color .name ()} >■</font>
585+ <b>{ escape (val ).replace ("-" , nbhp )} </b>:
586+ </td>
587+ <td>
588+ { n } ({ n / tot * 100 :.1f} %)
589+ </td>
590+ </tr>
591+ """ for color , val , n in zip (colors , values , distribution ) if n ) \
592+ + "</table>"
593+
573594 def _draw_pie_charts (self , sizes ):
574595 fx , fy = self ._grid_factors
575596 color_column = self ._get_color_column ()
@@ -578,12 +599,14 @@ def _draw_pie_charts(self, sizes):
578599 for x in range (self .size_x - self .hexagonal * (y % 2 )):
579600 r = sizes [x , y ]
580601 if not r :
602+ self .grid_cells [y , x ].setToolTip ("" )
581603 continue
582604 members = self .get_member_indices (x , y )
583605 color_dist = np .bincount (color_column [members ],
584606 minlength = len (colors ))
585- color_dist = color_dist .astype (float ) / len (members )
586- pie = PieChart (color_dist , r / 2 , colors )
607+ rel_color_dist = color_dist .astype (float ) / len (members )
608+ pie = PieChart (rel_color_dist , r / 2 , colors )
609+ pie .setToolTip (self ._tooltip (colors , color_dist ))
587610 self .elements .addToGroup (pie )
588611 pie .setPos (x + (y % 2 ) * fx , y * fy )
589612
@@ -609,6 +632,7 @@ def _draw_colored_circles(self, sizes):
609632 ellipse .setRect (x + (y % 2 ) * fx - r / 2 , y * fy - r / 2 , r , r )
610633 ellipse .setPen (pen )
611634 ellipse .setBrush (brush )
635+ ellipse .setToolTip (self ._tooltip (self .colors , bc ))
612636 self .elements .addToGroup (ellipse )
613637
614638 def redraw_grid (self ):
@@ -811,12 +835,7 @@ def create_legend(self):
811835 if self .attr_color .is_discrete :
812836 names = self .attr_color .values
813837 else :
814- sval = self .attr_color .repr_val
815- names = \
816- [f"< { sval (self .thresholds [0 ])} " ] \
817- + [f"{ sval (x )} - { sval (y )} "
818- for x , y in zip (self .thresholds , self .thresholds [1 :])] \
819- + [f"≥ { sval (self .thresholds [- 1 ])} " ]
838+ names = self ._bin_names ()
820839
821840 items = []
822841 size = 8
@@ -838,6 +857,14 @@ def create_legend(self):
838857 self .scene .addItem (self .legend )
839858 self .set_legend_pos ()
840859
860+ def _bin_names (self ):
861+ sval = self .attr_color .repr_val
862+ return \
863+ [f"< { sval (self .thresholds [0 ])} " ] \
864+ + [f"{ sval (x )} - { sval (y )} "
865+ for x , y in zip (self .thresholds , self .thresholds [1 :])] \
866+ + [f"≥ { sval (self .thresholds [- 1 ])} " ]
867+
841868 def set_legend_pos (self ):
842869 if self .legend is None :
843870 return
0 commit comments