Skip to content

Fix tick marker mirroring (matplotlib conversion) - #5310

Open
robertoffmoura wants to merge 2 commits into
plotly:mainfrom
robertoffmoura:rm/fix-tick-marker-mirroring
Open

Fix tick marker mirroring (matplotlib conversion)#5310
robertoffmoura wants to merge 2 commits into
plotly:mainfrom
robertoffmoura:rm/fix-tick-marker-mirroring

Conversation

@robertoffmoura

Copy link
Copy Markdown
Contributor

Hi,

This fixes the issue where a matplotlib figure with only bottom and left tick markers would be converted to a plotly figure with markers on all sides.

Code PR

  • I have read through the contributing notes and understand the structure of the package. In particular, if my PR modifies code of plotly.graph_objects, my modifications concern the code generator and not the generated files.
  • I have added tests or modified existing tests.
  • For a new feature, I have added documentation examples (please see the doc checklist as well).
  • I have added a CHANGELOG entry if changing anything substantial.
  • For a new feature or a change in behavior, I have updated the relevant docstrings in the code.

@robertoffmoura
robertoffmoura force-pushed the rm/fix-tick-marker-mirroring branch 2 times, most recently from 3fafa67 to daf0327 Compare August 8, 2025 11:06
@gvwilson
gvwilson requested a review from emilykl August 11, 2025 17:07
@gvwilson gvwilson added P1 needed for current cycle community community contribution fix fixes something broken labels Aug 11, 2025
@robertoffmoura
robertoffmoura force-pushed the rm/fix-tick-marker-mirroring branch from 860b8b0 to 001ff53 Compare August 12, 2025 09:31
@emilykl

emilykl commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

Hi @robertoffmoura, thank you for the fix! Same question here, could you provide some side-by-side comparisons to show the difference this PR introduces and why this is the correct behavior? I'm not very familiar with axis mirroring in matplotlib (or Plotly for that matter) so just trying to sanity check that these changes make sense.

I took a quick look at the images of the plots in the tests you added, and the only one where I see a difference between your branch and main is in the axis_mirror_false_with_one_sided_ticks function, is that expected?

@robertoffmoura
robertoffmoura force-pushed the rm/fix-tick-marker-mirroring branch from 001ff53 to 60cd4f7 Compare October 9, 2025 15:43
@robertclaus

Copy link
Copy Markdown

@robertoffmoura since this PR is quite old, should it be closed?

@robertoffmoura
robertoffmoura force-pushed the rm/fix-tick-marker-mirroring branch from 60cd4f7 to e342e72 Compare August 10, 2026 17:03
@robertoffmoura

Copy link
Copy Markdown
Contributor Author

Hi @emilykl and @robertclaus,

I just updated the PR. Please see the table below with side-by-side comparisons to show the difference this PR introduces and why this is the correct behaviour, along with the code snippet to generate these plots.

Config matplotlib plotly before PR plotly after PR Notes
01
no line,
no ticks
01_no_line_no_ticks_mpl 01_no_line_no_ticks_plotly 01_no_line_no_ticks_plotly_after Before: phantom bottom/left tick markers drawn despite mpl having none (hardcoded ticks="inside"). After: tick markers hidden (ticks=""), matches mpl.
02
no line,
ticks
02_no_line_ticks_mpl 02_no_line_ticks_plotly 02_no_line_ticks_plotly_after Unchanged: line hidden, ticks preserved (already correct).
03
line,
no ticks
03_line_no_ticks_mpl 03_line_no_ticks_plotly 03_line_no_ticks_plotly_after Before: phantom tick markers. After: tick markers hidden, only the axis line remains, matches mpl.
04
line,
ticks
04_line_ticks_mpl 04_line_ticks_plotly 04_line_ticks_plotly_after Before: missing left axis. After: Both axes present, matches mpl
05
box,
no ticks
05_box_no_ticks_mpl 05_box_no_ticks_plotly 05_box_no_ticks_plotly_after Before: drew phantom ticks on all four sides. After: box only, no ticks, matches mpl.
06
box,
main ticks
06_box_main_ticks_mpl 06_box_main_ticks_plotly 06_box_main_ticks_plotly_after Before: drew phantom ticks on top/right. After: box with ticks only on bottom/left, matches mpl. This is the default mpl figure, so it affects every default conversion.
07
box,
all ticks
07_box_all_ticks_mpl 07_box_all_ticks_plotly 07_box_all_ticks_plotly_after Unchanged: box with ticks on all four sides (already correct).

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import plotly.tools as tls

# All plotly (showline, ticks, mirror) configurations reachable from matplotlib:
#   main_spine: bottom/left spine visible -> showline
#   mirror_spine: top/right spine visible -> line mirrored (mirror True/"ticks")
#   main_tick: bottom/left tick markers  -> ticks "inside"
#   mirror_tick: top/right tick markers  -> mirror "ticks" (mirrored line + ticks)
configs = [
    ("01_no_line_no_ticks",       dict(main_sp=False, mir_sp=False, main_tk=False, mir_tk=False)),
    ("02_no_line_ticks",          dict(main_sp=False, mir_sp=False, main_tk=True,  mir_tk=False)),
    ("03_line_no_ticks",          dict(main_sp=True,  mir_sp=False, main_tk=False, mir_tk=False)),
    ("04_line_ticks",             dict(main_sp=True,  mir_sp=False, main_tk=True,  mir_tk=False)),
    ("05_box_no_ticks",           dict(main_sp=True,  mir_sp=True,  main_tk=False, mir_tk=False)),
    ("06_box_main_ticks",         dict(main_sp=True,  mir_sp=True,  main_tk=True,  mir_tk=False)),
    ("07_box_all_ticks",          dict(main_sp=True,  mir_sp=True,  main_tk=True,  mir_tk=True)),
]

for name, cfg in configs:
    fig, ax = plt.subplots(figsize=(4, 3))
    ax.plot([0, 1], [0, 1])
    ax.spines["bottom"].set_visible(cfg["main_sp"])
    ax.spines["left"].set_visible(cfg["main_sp"])
    ax.spines["top"].set_visible(cfg["mir_sp"])
    ax.spines["right"].set_visible(cfg["mir_sp"])
    ax.tick_params(
        bottom=cfg["main_tk"], left=cfg["main_tk"],
        top=cfg["mir_tk"], right=cfg["mir_tk"],
    )

    fig.savefig(f"{name}_mpl.png")

    p = tls.mpl_to_plotly(fig)
    p.write_image(f"{name}_plotly.png")

    x = p.layout.xaxis
    print(f"{name}: showline={x.showline!r:<6} ticks={x.ticks!r:<10} mirror={x.mirror!r}")

@robertoffmoura
robertoffmoura force-pushed the rm/fix-tick-marker-mirroring branch from e342e72 to c29b7fb Compare August 10, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community community contribution fix fixes something broken P1 needed for current cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants