Skip to content

Commit df1a759

Browse files
Fix tick marker mirroring
1 parent 694b036 commit df1a759

File tree

4 files changed

+95
-10
lines changed

4 files changed

+95
-10
lines changed

plotly/matplotlylib/mpltools.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,12 @@ def get_axes_bounds(fig):
265265
return (x_min, x_max), (y_min, y_max)
266266

267267

268-
def get_axis_mirror(main_spine, mirror_spine):
269-
if main_spine and mirror_spine:
268+
def get_axis_mirror(main_spine, mirror_spine, main_tick_markers, mirror_tick_markers):
269+
if main_spine and mirror_spine and main_tick_markers and mirror_tick_markers:
270270
return "ticks"
271-
elif main_spine and not mirror_spine:
272-
return False
273-
elif not main_spine and mirror_spine:
274-
return False # can't handle this case yet!
275-
else:
276-
return False # nuttin'!
271+
if main_spine and mirror_spine:
272+
return True
273+
return False
277274

278275

279276
def get_bar_gap(bar_starts, bar_ends, tol=1e-10):

plotly/matplotlylib/renderer.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,16 @@ def open_axes(self, ax, props):
168168
top_spine = mpltools.get_spine_visible(ax, "top")
169169
left_spine = mpltools.get_spine_visible(ax, "left")
170170
right_spine = mpltools.get_spine_visible(ax, "right")
171-
xaxis["mirror"] = mpltools.get_axis_mirror(bottom_spine, top_spine)
172-
yaxis["mirror"] = mpltools.get_axis_mirror(left_spine, right_spine)
171+
bottom_tick_markers = ax.xaxis.get_tick_params()["bottom"]
172+
top_tick_markers = ax.xaxis.get_tick_params()["top"]
173+
left_tick_markers = ax.yaxis.get_tick_params()["left"]
174+
right_tick_markers = ax.yaxis.get_tick_params()["right"]
175+
xaxis["mirror"] = mpltools.get_axis_mirror(
176+
bottom_spine, top_spine, bottom_tick_markers, top_tick_markers
177+
)
178+
yaxis["mirror"] = mpltools.get_axis_mirror(
179+
left_spine, right_spine, left_tick_markers, right_tick_markers
180+
)
173181
xaxis["showline"] = bottom_spine
174182
yaxis["showline"] = top_spine
175183

plotly/matplotlylib/tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import matplotlib
2+
3+
matplotlib.use("Agg")
4+
import matplotlib.pyplot as plt
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import plotly.tools as tls
2+
3+
from . import plt
4+
5+
def test_axis_mirror_with_spines_and_ticks():
6+
"""Test that mirror=True when both spines and ticks are visible on both sides."""
7+
fig, ax = plt.subplots()
8+
ax.plot([0, 1], [0, 1])
9+
10+
# Show all spines
11+
ax.spines['top'].set_visible(True)
12+
ax.spines['bottom'].set_visible(True)
13+
ax.spines['left'].set_visible(True)
14+
ax.spines['right'].set_visible(True)
15+
16+
# Show ticks on all sides
17+
ax.tick_params(top=True, bottom=True, left=True, right=True)
18+
19+
plotly_fig = tls.mpl_to_plotly(fig)
20+
21+
assert plotly_fig.layout.xaxis.mirror == "ticks"
22+
assert plotly_fig.layout.yaxis.mirror == "ticks"
23+
24+
25+
def test_axis_mirror_with_ticks_only():
26+
"""Test that mirror=False when spines are not visible on both sides."""
27+
fig, ax = plt.subplots()
28+
ax.plot([0, 1], [0, 1])
29+
30+
# Hide opposite spines
31+
ax.spines['top'].set_visible(False)
32+
ax.spines['right'].set_visible(False)
33+
34+
# Show ticks on all sides
35+
ax.tick_params(top=True, bottom=True, left=True, right=True)
36+
37+
plotly_fig = tls.mpl_to_plotly(fig)
38+
39+
assert plotly_fig.layout.xaxis.mirror == False
40+
assert plotly_fig.layout.yaxis.mirror == False
41+
42+
43+
def test_axis_mirror_false_with_one_sided_ticks():
44+
"""Test that mirror=True when ticks are only on one side but spines are
45+
visible on both sides."""
46+
fig, ax = plt.subplots()
47+
ax.plot([0, 1], [0, 1])
48+
49+
# Default matplotlib behavior - ticks only on bottom and left
50+
ax.tick_params(top=False, bottom=True, left=True, right=False)
51+
52+
plotly_fig = tls.mpl_to_plotly(fig)
53+
54+
assert plotly_fig.layout.xaxis.mirror == True
55+
assert plotly_fig.layout.yaxis.mirror == True
56+
57+
58+
def test_axis_mirror_mixed_configurations():
59+
"""Test different configurations for x and y axes."""
60+
fig, ax = plt.subplots()
61+
ax.plot([0, 1], [0, 1])
62+
63+
# X-axis: spines and ticks on both sides (mirror="ticks")
64+
ax.spines['top'].set_visible(True)
65+
ax.spines['bottom'].set_visible(True)
66+
ax.tick_params(top=True, bottom=True)
67+
68+
# Y-axis: spine only on one side (mirror=False)
69+
ax.spines['right'].set_visible(False)
70+
ax.spines['left'].set_visible(True)
71+
ax.tick_params(left=True, right=True)
72+
73+
plotly_fig = tls.mpl_to_plotly(fig)
74+
75+
assert plotly_fig.layout.xaxis.mirror == "ticks"
76+
assert plotly_fig.layout.yaxis.mirror == False

0 commit comments

Comments
 (0)