dash icon indicating copy to clipboard operation
dash copied to clipboard

append not working as expected with partial property updates

Open Coding-with-Adam opened this issue 1 year ago • 1 comments

Issue reported by community on the forum. @T4rk1n and I took a deeper look into it but we couldn't pinpoint the location of the bug exactly. There may be a bug in the graph component or Plotly.js.

The Problem

The append Patch method does not work, although it's nearly an exact replica of this example code in the docs.

It appears to create a new line on first call, then it appends to the new line for the subsequent call. According to @T4rk1n , it's actually not a new line but it draws the first appended item from the first point on the line.

from dash import Dash, html, dcc, Input, Output, Patch, callback, State
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import datetime
import random

app = Dash(__name__)

# Create a subplot with 2 rows and 1 column
fig = make_subplots(rows=2, cols=1, shared_xaxes=True)

# Initialize the figure with some default data
initial_x = [datetime.datetime.now() - datetime.timedelta(minutes=i) for i in range(5)]
initial_y1 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y2 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y3 = [random.randrange(1, 30, 1) for _ in range(5)]
initial_y4 = [random.randrange(1, 30, 1) for _ in range(5)]

fig.add_trace(go.Scatter(x=initial_x, y=initial_y1, mode='lines+markers', name='Trace 1.1'), row=1, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y2, mode='lines+markers', name='Trace 1.2'), row=1, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y3, mode='lines+markers', name='Trace 2.1'), row=2, col=1)
fig.add_trace(go.Scatter(x=initial_x, y=initial_y4, mode='lines+markers', name='Trace 2.2'), row=2, col=1)
# print(fig)

app.layout = html.Div(
    [
        html.Button("Append", id="append-new-val"),
        dcc.Graph(figure=fig, id="append-example-graph"),
    ]
)


@callback(
    Output("append-example-graph", "figure"),
    Input("append-new-val", "n_clicks"),
    State("append-example-graph", "figure"),
    prevent_initial_call=True,
)
def add_data_to_fig(n_clicks, fig1):
    current_time = datetime.datetime.now()
    # Generate random values for each trace
    random_values = [random.randrange(1, 30, 1) for _ in range(4)]
    patched_figure = Patch()

    # Update first subplot, first trace
    patched_figure["data"][0]["x"].append(current_time)
    patched_figure["data"][0]["y"].append(random_values[0])

    # # Update first subplot, second trace
    # patched_figure["data"][1]["x"].append(current_time)
    # patched_figure["data"][1]["y"].append(random_values[1])
    #
    # # Update second subplot, first trace
    # patched_figure["data"][2]["x"].append(current_time)
    # patched_figure["data"][2]["y"].append(random_values[2])
    #
    # # Update second subplot, second trace
    # patched_figure["data"][3]["x"].append(current_time)
    # patched_figure["data"][3]["y"].append(random_values[3])
    # # print('')
    # # print(fig1)

    return patched_figure


if __name__ == "__main__":
    app.run(debug=True)

Coding-with-Adam avatar Jul 23 '24 14:07 Coding-with-Adam