1515from .widgets import ClickableHTML
1616
1717
18- def min_with_none (a , b ):
18+ def _min_with_none (a , b ):
1919 return a if b is None else min (a , b )
2020
2121
22- def max_with_none (a , b ):
22+ def _max_with_none (a , b ):
2323 return a if b is None else max (a , b )
2424
2525
26+ def _em_to_px (em_value ):
27+ """Convert em units to pixels using standard conversion (1em = 16px)."""
28+ return int (em_value * 16 )
29+
30+
31+ def _multiply_font_size (fontsize , multiplier ):
32+ """
33+ Multiply a font size by a factor.
34+
35+ Args:
36+ fontsize: Font size string (e.g., "1.2em", "14px", "10pt")
37+ multiplier: Factor to multiply by
38+
39+ Returns:
40+ String with multiplied font size
41+ """
42+ value = float (fontsize [:- 2 ])
43+ unit = fontsize [- 2 :]
44+ result_value = value * multiplier
45+ return f"{ result_value } { unit } "
46+
47+
2648class Axes (ipw .GridBox ):
2749 def __init__ (self , * , ax : MplAxes , figure = None ) -> None :
2850 self .background_color = "#ffffff"
@@ -305,10 +327,10 @@ def autoscale(self):
305327 ymax = None
306328 for artist in self ._artists :
307329 lims = artist .get_bbox ()
308- xmin = min_with_none (lims ["left" ], xmin )
309- xmax = max_with_none (lims ["right" ], xmax )
310- ymin = min_with_none (lims ["bottom" ], ymin )
311- ymax = max_with_none (lims ["top" ], ymax )
330+ xmin = _min_with_none (lims ["left" ], xmin )
331+ xmax = _max_with_none (lims ["right" ], xmax )
332+ ymin = _min_with_none (lims ["bottom" ], ymin )
333+ ymax = _max_with_none (lims ["top" ], ymax )
312334 self ._xmin = (
313335 xmin
314336 if xmin is not None
@@ -355,13 +377,11 @@ def _make_xticks(self):
355377 trans_data = self ._ax .transData
356378 xticks_axes = inv_trans_axes .transform (trans_data .transform (xy ))[:, 0 ]
357379
358- # width = f"calc({self.width}px + 0.5em)"
359-
380+ height_px = _em_to_px (1.2 ) + tick_length + label_offset
360381 bottom_string = [
361382 (
362- f'<svg height="calc(1.2em + { tick_length } px + { label_offset } px) " '
383+ f'<svg height="{ height_px } px" '
363384 f'width="{ self .width } "><line x1="0" y1="0" '
364- # f'width="calc(0.5em + {self.width}px)"><line x1="0" y1="0" '
365385 f'x2="{ self .width } " y2="0" '
366386 f'style="stroke:black;stroke-width:{ self ._spine_linewidth } " />'
367387 )
@@ -426,16 +446,16 @@ def _make_yticks(self):
426446 # Predict width of the left margin based on the longest label
427447 # Need to convert to integer to avoid sub-pixel rendering issues
428448 max_length = math .ceil (max (lab .get_tightbbox ().width for lab in ylabels ))
429- width = f"calc( { max_length } px + { tick_length } px + { label_offset } px)"
430- width1 = f"calc( { max_length } px + { label_offset } px)"
431- width2 = f"calc( { max_length } px)"
432- width3 = f"calc( { max_length } px + { tick_length * 0.3 } px + { label_offset } px)"
449+ width_px = max_length + tick_length + label_offset
450+ width1_px = max_length + label_offset
451+ width2_px = max_length
452+ width3_px = max_length + int ( tick_length * 0.3 ) + label_offset
433453
434454 left_string = [
435455 (
436- f'<svg height="{ self .height } " width="{ width } ">'
437- f'<line x1="{ width } " y1="0" '
438- f'x2="{ width } " y2="{ self .height } " '
456+ f'<svg height="{ self .height } " width="{ width_px } px ">'
457+ f'<line x1="{ width_px } " y1="0" '
458+ f'x2="{ width_px } " y2="{ self .height } " '
439459 f'style="stroke:black;stroke-width:{ self ._spine_linewidth } " />'
440460 )
441461 ]
@@ -451,13 +471,13 @@ def _make_yticks(self):
451471 continue
452472 y = self .height - (tick * self .height )
453473 left_string .append (
454- f'<line x1="{ width } " y1="{ y } " '
455- f'x2="{ width1 } " y2="{ y } " '
474+ f'<line x1="{ width_px } " y1="{ y } " '
475+ f'x2="{ width1_px } " y2="{ y } " '
456476 'style="stroke:black;stroke-width:1" />'
457477 )
458478
459479 left_string .append (
460- f'<text x="{ width2 } " '
480+ f'<text x="{ width2_px } " '
461481 f'y="{ y } " text-anchor="end" dominant-baseline="middle">'
462482 f"{ html_to_svg (latex_to_html (label ), baseline = 'middle' )} </text>"
463483 )
@@ -472,8 +492,8 @@ def _make_yticks(self):
472492 continue
473493 y = self .height - (tick * self .height )
474494 left_string .append (
475- f'<line x1="{ width } " y1="{ y } " '
476- f'x2="{ width3 } " y2="{ y } " '
495+ f'<line x1="{ width_px } " y1="{ y } " '
496+ f'x2="{ width3_px } " y2="{ y } " '
477497 'style="stroke:black;stroke-width:0.5" />'
478498 )
479499
@@ -621,12 +641,10 @@ def toggle_pan(self, value):
621641
622642 def set_xlabel (self , label , fontsize = "1.1em" ):
623643 if label :
624- # Height should be 115% of fontsize to account for line height
625- # height = "calc(1.15 * {fontsize})"
644+ height = _multiply_font_size (fontsize , 1.3 )
626645 self ._margins ["xlabel" ].value = (
627646 '<div style="position:relative; '
628- # f'width: {self.width}px; height: {fontsize};">'
629- f'width: { self .width } px; height: calc(1.3 * { fontsize } );">'
647+ f'width: { self .width } px; height: { height } ;">'
630648 '<div style="position:relative; top: 50%;left: 50%; '
631649 f"transform: translate(-50%, -50%); font-size: { fontsize } ;"
632650 f'float:left;">{ label .replace (" " , " " )} </div></div>'
@@ -640,9 +658,10 @@ def get_xlabel(self):
640658
641659 def set_ylabel (self , label , fontsize = "1.1em" ):
642660 if label :
661+ width = _multiply_font_size (fontsize , 1.25 )
643662 self ._margins ["ylabel" ].value = (
644663 '<div style="position:relative; '
645- f'width: calc(1.25 * { fontsize } ) ; height: { self .height } px;">'
664+ f'width: { width } ; height: { self .height } px;">'
646665 '<div style="position:relative; top: 50%;left: 50%; '
647666 f"transform: translate(-50%, -50%) rotate(-90deg); "
648667 f"font-size: { fontsize } ;"
@@ -657,9 +676,10 @@ def get_ylabel(self):
657676
658677 def set_title (self , title , fontsize = "1.2em" ):
659678 if title :
679+ height = _multiply_font_size (fontsize , 1.3 )
660680 self ._margins ["title" ].value = (
661681 '<div style="position:relative; '
662- f'width: { self .width } px; height: calc(1.3 * { fontsize } ) ;">'
682+ f'width: { self .width } px; height: { height } ;">'
663683 '<div style="position:relative; top: 50%;left: 50%; '
664684 f"transform: translate(-50%, -50%); font-size: { fontsize } ;"
665685 f'float:left;">{ title .replace (" " , " " )} </div></div>'
0 commit comments