Skip to content

Commit 0607ba1

Browse files
authored
Merge branch 'main' into rm/fix-tick-marker-mirroring
2 parents a79b87c + 73f86fd commit 0607ba1

5 files changed

Lines changed: 64 additions & 15 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55
## Unreleased
66

77
### Fixed
8+
- Fix `mpl_to_plotly` tick marker mirroring, axis positioning, and trace visibility for twinned and overlaid subplots (such as `twinx` and `twiny`) [[#5310](https://github.com/plotly/plotly.py/pull/5310)], with thanks to @robertoffmoura for the contribution!
89
- Fix concurrent first access to lazily initialized graph object properties, which could raise `ValueError("Invalid value")` [[#5691](https://github.com/plotly/plotly.py/pull/5691)], with thanks to @hb1915 for the contribution!
910
- Fix `mpl_to_plotly` crashing on touching bars (such as `plt.hist`) due to floating-point noise producing negative `bargap` values by clamping `bargap` to `[0, 1]` [[#5696](https://github.com/plotly/plotly.py/pull/5696)], with thanks to @robertoffmoura for the contribution!
10-
- Fix `mpl_to_plotly` tick marker mirroring, axis positioning, and trace visibility for twinned and overlaid subplots (such as `twinx` and `twiny`) [[#5310](https://github.com/plotly/plotly.py/pull/5310)], with thanks to @robertoffmoura for the contribution!
11+
- Export tick label colors to the plotly tickfont in `mpl_to_plotly` [[#5716](https://github.com/plotly/plotly.py/pull/5716)], with thanks to @robertoffmoura for the contribution!
1112
- Fix `px.sunburst`, `px.treemap` and `px.icicle` listing sectors in a different order on every run when `path` is used with a Polars DataFrame; sectors now follow their order of first appearance for all dataframe backends [[#5766](https://github.com/plotly/plotly.py/pull/5766)], with thanks to @Irahan2 for the contribution!
1213

1314
## [7.1.0] - 2026-09-15

‎plotly/matplotlylib/mplexporter/utils.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,15 @@ def get_axis_properties(axis):
257257
# Get axis scale
258258
props["scale"] = axis.get_scale()
259259

260-
# Get major tick label size (assumes that's all we really care about!)
260+
# Get major tick label size and color (assumes that's all we really
261+
# care about!)
261262
labels = axis.get_ticklabels()
262263
if labels:
263264
props["fontsize"] = labels[0].get_fontsize()
265+
props["fontcolor"] = export_color(labels[0].get_color())
264266
else:
265267
props["fontsize"] = None
268+
props["fontcolor"] = None
266269

267270
# Get associated grid
268271
props["grid"] = get_grid_style(axis)

‎plotly/matplotlylib/mpltools.py‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,14 +513,32 @@ def prep_ticks(ax, index, ax_type, props):
513513
return axis_dict
514514

515515

516+
def _export_color(color):
517+
"""Export a matplotlib color for use as a plotly color.
518+
519+
matplotlib uses "none" for fully transparent colors, which plotly does not
520+
accept, so transparent colors are exported as transparent black.
521+
Colors already exported by the mplexporter (hex or rgba strings) are
522+
passed through unchanged.
523+
"""
524+
if color is None:
525+
return None
526+
if isinstance(color, str):
527+
return color if color != "none" else "rgba(0,0,0,0)"
528+
return [_export_color(c) for c in color]
529+
530+
516531
def prep_xy_axis(ax, props, x_bounds, y_bounds):
517532
xaxis = dict(
518533
type=props["axes"][0]["scale"],
519534
range=list(props["xlim"]),
520535
showgrid=props["axes"][0]["grid"]["gridOn"],
521536
domain=convert_x_domain(props["bounds"], x_bounds),
522537
side=props["axes"][0]["position"],
523-
tickfont=dict(size=props["axes"][0]["fontsize"]),
538+
tickfont=dict(
539+
size=props["axes"][0]["fontsize"],
540+
color=_export_color(props["axes"][0]["fontcolor"]),
541+
),
524542
)
525543
xaxis.update(prep_ticks(ax, 0, "x", props))
526544
yaxis = dict(
@@ -529,7 +547,10 @@ def prep_xy_axis(ax, props, x_bounds, y_bounds):
529547
showgrid=props["axes"][1]["grid"]["gridOn"],
530548
domain=convert_y_domain(props["bounds"], y_bounds),
531549
side=props["axes"][1]["position"],
532-
tickfont=dict(size=props["axes"][1]["fontsize"]),
550+
tickfont=dict(
551+
size=props["axes"][1]["fontsize"],
552+
color=_export_color(props["axes"][1]["fontcolor"]),
553+
),
533554
)
534555
yaxis.update(prep_ticks(ax, 1, "y", props))
535556
return xaxis, yaxis

‎plotly/matplotlylib/renderer.py‎

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,7 @@
1414
from plotly.matplotlylib import mpltools
1515

1616

17-
def _export_color(color):
18-
"""Export a matplotlib color for use as a plotly color.
19-
20-
matplotlib uses "none" for fully transparent colors, which plotly does not
21-
accept, so transparent colors are exported as transparent black.
22-
Colors already exported by the mplexporter (hex or rgba strings) are
23-
passed through unchanged.
24-
"""
25-
if isinstance(color, str):
26-
return "rgba(0,0,0,0)" if color == "none" else color
27-
return [_export_color(c) for c in color]
17+
from plotly.matplotlylib.mpltools import _export_color
2818

2919

3020
class PlotlyRenderer(Renderer):

‎plotly/matplotlylib/tests/test_renderer.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,37 @@ def test_custom_date_xtickvals_given_as_numbers_are_converted():
565565
"2023-01-07 00:00:00",
566566
"2023-01-10 00:00:00",
567567
)
568+
569+
570+
def test_tick_label_color_exports():
571+
"""Tick label colors are exported to the plotly tickfont."""
572+
fig, ax = plt.subplots()
573+
ax.plot([0, 1], [0, 1])
574+
575+
plotly_fig = tls.mpl_to_plotly(fig)
576+
577+
assert plotly_fig.layout.xaxis.tickfont.color == "#000000"
578+
579+
580+
def test_dark_tick_label_color_exports():
581+
"""Dark-background tick label colors are exported to the plotly
582+
tickfont."""
583+
with plt.style.context("dark_background"):
584+
fig, ax = plt.subplots()
585+
ax.plot([0, 1], [0, 1])
586+
587+
plotly_fig = tls.mpl_to_plotly(fig)
588+
589+
assert plotly_fig.layout.xaxis.tickfont.color == "#FFFFFF"
590+
591+
592+
def test_transparent_tick_label_color_exports():
593+
"""Transparent tick label colors ('none') export as transparent rgba."""
594+
fig, ax = plt.subplots()
595+
ax.plot([0, 1], [0, 1])
596+
ax.tick_params(labelcolor="none")
597+
598+
plotly_fig = tls.mpl_to_plotly(fig)
599+
600+
assert plotly_fig.layout.xaxis.tickfont.color == "rgba(0,0,0,0)"
601+
assert plotly_fig.layout.yaxis.tickfont.color == "rgba(0,0,0,0)"

0 commit comments

Comments
 (0)