plotly/plotly.py

[BUG]: error_y.array renders error bars before initial render but not after Plotly.restyle

Open

#5,621 建立於 2026年6月8日

在 GitHub 查看
 (2 留言) (0 反應) (0 負責人)Python (2,467 fork)batch import
buggood first issuegood for agent

倉庫指標

Star
 (14,684 star)
PR 合併指標
 (平均合併 1天 7小時) (30 天內合併 7 個 PR)

描述

Description

A scatter trace renders error_y.array differently depending on when the property is applied.

If error_y.array is set before the first render, vertical error bars are visible. If the same base figure is rendered first and the same error_y.array value is applied later with Plotly.restyle, the error bars are not shown.

Screenshots/Video

Steps to reproduce

import io

import pandas as pd
import plotly
import plotly.express as px
import plotly.io as pio
from PIL import Image, ImageChops
from playwright.sync_api import sync_playwright


print(f"Plotly version: {plotly.__version__}")


def make_fig():
    df = pd.DataFrame(
        {
            "x": [3.0, 3.2, 3.4],
            "y": [5.0, 4.8, 5.4],
            "color": [5.0, 4.8, 5.4],
        }
    )
    return px.scatter(
        df,
        x="x",
        y="y",
        color="color",
        color_continuous_scale=px.colors.sequential.Viridis,
    )


error_array = [0.0, 0.5, 1.0]

# Case 1: set error_y.array before the initial render.
fig1 = make_fig()
fig1.data[0].error_y.array = error_array
assert tuple(fig1.data[0].error_y.array) == tuple(error_array)
html1 = pio.to_html(fig1, full_html=True, include_plotlyjs=True)

# Case 2: render first, then apply the same value with Plotly.restyle.
fig2 = make_fig()
html2 = pio.to_html(fig2, full_html=True, include_plotlyjs=True)
html2 = html2.replace(
    "</body>",
    """
<script>
window.addEventListener("DOMContentLoaded", () => {
    const plotEl = document.getElementsByClassName("plotly-graph-div")[0];
    setTimeout(() => {
        Plotly.restyle(plotEl, {"error_y.array": [0.0, 0.5, 1.0]}, [0]);
    }, 1000);
});
</script>
</body>""",
)

with sync_playwright() as playwright:
    browser = playwright.chromium.launch(
        headless=True,
        args=["--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],
    )
    page = browser.new_page(viewport={"width": 1200, "height": 800})

    page.set_content(html1, wait_until="domcontentloaded")
    page.wait_for_timeout(1500)
    img1 = page.screenshot(path="plot1.png")

    page.set_content(html2, wait_until="domcontentloaded")
    page.wait_for_timeout(2000)
    img2 = page.screenshot(path="plot2.png")

    browser.close()

diff = ImageChops.difference(
    Image.open(io.BytesIO(img1)).convert("RGB"),
    Image.open(io.BytesIO(img2)).convert("RGB"),
)

print("Saved plot1.png (Python-side before render)")
print("Saved plot2.png (JS-side restyle after render)")
assert diff.getbbox() is not None, "Reproducer did not reproduce: images are identical."
print("Bug reproduced: the two renderings differ.")

Notes

Add info here that doesn't fit in the other sections.

貢獻者指南