Skip to content

Commit 3fafa67

Browse files
Fix tick marker mirroring
1 parent 1ec864b commit 3fafa67

File tree

4 files changed

+94
-10
lines changed

4 files changed

+94
-10
lines changed

plotly/matplotlylib/mpltools.py

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

268268

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

279276

280277
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: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 == True
22+
assert plotly_fig.layout.yaxis.mirror == True
23+
24+
25+
def test_axis_mirror_with_ticks_only():
26+
"""Test that mirror='ticks' when only ticks are 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 == "ticks"
40+
assert plotly_fig.layout.yaxis.mirror == "ticks"
41+
42+
43+
def test_axis_mirror_false_with_one_sided_ticks():
44+
"""Test that mirror=False when ticks are only on one side."""
45+
fig, ax = plt.subplots()
46+
ax.plot([0, 1], [0, 1])
47+
48+
# Default matplotlib behavior - ticks only on bottom and left
49+
ax.tick_params(top=False, bottom=True, left=True, right=False)
50+
51+
plotly_fig = tls.mpl_to_plotly(fig)
52+
53+
assert plotly_fig.layout.xaxis.mirror == False
54+
assert plotly_fig.layout.yaxis.mirror == False
55+
56+
57+
def test_axis_mirror_mixed_configurations():
58+
"""Test different configurations for x and y axes."""
59+
fig, ax = plt.subplots()
60+
ax.plot([0, 1], [0, 1])
61+
62+
# X-axis: spines and ticks on both sides (mirror=True)
63+
ax.spines['top'].set_visible(True)
64+
ax.spines['bottom'].set_visible(True)
65+
ax.tick_params(top=True, bottom=True)
66+
67+
# Y-axis: only ticks on both sides (mirror='ticks')
68+
ax.spines['right'].set_visible(False)
69+
ax.spines['left'].set_visible(True)
70+
ax.tick_params(left=True, right=True)
71+
72+
plotly_fig = tls.mpl_to_plotly(fig)
73+
74+
assert plotly_fig.layout.xaxis.mirror == True
75+
assert plotly_fig.layout.yaxis.mirror == "ticks"

0 commit comments

Comments
 (0)