Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions plotly/matplotlylib/mpltools.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,12 @@ def get_axes_bounds(fig):
return (x_min, x_max), (y_min, y_max)


def get_axis_mirror(main_spine, mirror_spine):
if main_spine and mirror_spine:
def get_axis_mirror(main_spine, mirror_spine, main_tick_markers, mirror_tick_markers):
if main_spine and mirror_spine and main_tick_markers and mirror_tick_markers:
return "ticks"
elif main_spine and not mirror_spine:
return False
elif not main_spine and mirror_spine:
return False # can't handle this case yet!
else:
return False # nuttin'!
if main_spine and mirror_spine:
return True
return False


def get_bar_gap(bar_starts, bar_ends, tol=1e-10):
Expand Down
12 changes: 10 additions & 2 deletions plotly/matplotlylib/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,16 @@ def open_axes(self, ax, props):
top_spine = mpltools.get_spine_visible(ax, "top")
left_spine = mpltools.get_spine_visible(ax, "left")
right_spine = mpltools.get_spine_visible(ax, "right")
xaxis["mirror"] = mpltools.get_axis_mirror(bottom_spine, top_spine)
yaxis["mirror"] = mpltools.get_axis_mirror(left_spine, right_spine)
bottom_tick_markers = ax.xaxis.get_tick_params()["bottom"]
top_tick_markers = ax.xaxis.get_tick_params()["top"]
left_tick_markers = ax.yaxis.get_tick_params()["left"]
right_tick_markers = ax.yaxis.get_tick_params()["right"]
xaxis["mirror"] = mpltools.get_axis_mirror(
bottom_spine, top_spine, bottom_tick_markers, top_tick_markers
)
yaxis["mirror"] = mpltools.get_axis_mirror(
left_spine, right_spine, left_tick_markers, right_tick_markers
)
xaxis["showline"] = bottom_spine
yaxis["showline"] = top_spine

Expand Down
75 changes: 75 additions & 0 deletions plotly/matplotlylib/tests/test_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,78 @@ def test_multiple_traces_native_legend():
assert plotly_fig.data[0].mode == "lines"
assert plotly_fig.data[1].mode == "markers"
assert plotly_fig.data[2].mode == "lines+markers"



def test_axis_mirror_with_spines_and_ticks():
"""Test that mirror=True when both spines and ticks are visible on both sides."""
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1])

# Show all spines
ax.spines["top"].set_visible(True)
ax.spines["bottom"].set_visible(True)
ax.spines["left"].set_visible(True)
ax.spines["right"].set_visible(True)

# Show ticks on all sides
ax.tick_params(top=True, bottom=True, left=True, right=True)

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.xaxis.mirror == "ticks"
assert plotly_fig.layout.yaxis.mirror == "ticks"


def test_axis_mirror_with_ticks_only():
"""Test that mirror=False when spines are not visible on both sides."""
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1])

# Hide opposite spines
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)

# Show ticks on all sides
ax.tick_params(top=True, bottom=True, left=True, right=True)

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.xaxis.mirror == False
assert plotly_fig.layout.yaxis.mirror == False


def test_axis_mirror_false_with_one_sided_ticks():
"""Test that mirror=True when ticks are only on one side but spines are
visible on both sides."""
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1])

# Default matplotlib behavior - ticks only on bottom and left
ax.tick_params(top=False, bottom=True, left=True, right=False)

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.xaxis.mirror == True
assert plotly_fig.layout.yaxis.mirror == True


def test_axis_mirror_mixed_configurations():
"""Test different configurations for x and y axes."""
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1])

# X-axis: spines and ticks on both sides (mirror="ticks")
ax.spines["top"].set_visible(True)
ax.spines["bottom"].set_visible(True)
ax.tick_params(top=True, bottom=True)

# Y-axis: spine only on one side (mirror=False)
ax.spines["right"].set_visible(False)
ax.spines["left"].set_visible(True)
ax.tick_params(left=True, right=True)

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.xaxis.mirror == "ticks"
assert plotly_fig.layout.yaxis.mirror == False