Search code examples
pythoncallbackplotlyplotly-dash

plotly.scatter figure doesnt reset when updating with callback (python dash)


I have the following problem:

I try to plot a plotly.scatter plot combined with dash which should be changeable with sliders using callback. I searched through the documentation of dash and plotly and found some examples for basic and advanced callbacks and also for Sliders

https://dash.plotly.com/basic-callbacks

https://dash.plotly.com/advanced-callbacks

https://dash.plotly.com/dash-core-components/slider

The Sliders are working and the shown data is also changing but the old plot doesnt vanish even if i reload the page. I dont know if the problem is in the html component or in the callback.

from math import cos,sin,radians
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from dash import Dash, dcc, html, Input, Output, callback
import pandas as pd

I skip the calculation which is not called in the callback because im quite sure the problem isnt there but if you want i can provide it aswell.

def s_out(XTvar, YTvar, ZTvar, XCvar, YCvar, ZCvar):
    for a in np.linspace(0,360,3600):
        s1i=cos(radians(a))
        s2i=sin(radians(a))
        fe=fE_tsaiwu((s1i,s2i,0,0,0,0),getm(XTvar, YTvar, ZTvar, XCvar, YCvar,ZCvar))
        s1.append(s1i/fe)
        s2.append(s2i/fe)
    return s1, s2

s1, s2 = s_out(XTvar, YTvar, ZTvar, XCvar, YCvar, ZCvar)

Html component with callback:
(Initialising the figure in the Div is not even necessary i figured out)

app = Dash(__name__)

app.layout = html.Div([
    dcc.Graph(
        id='Tsai',
        # figure=fig
        figure = {}
    ),
    html.H3(children='XTvar'),
    html.H5(children='Der Wert des Sliders wird hier direkt unter dem momentanen Punkt angezeigt'),
    dcc.Slider(
        id= "XTvar",
        min = 1,
        max = 1500,
        value = 1000,
           tooltip={"placement": "bottom", "always_visible": True}
    ),
    html.H3(children='YTvar'),
    dcc.Slider(
        id= "YTvar",
        min = 1,
        max = 50,
        value = 40,
    ),
    html.H3(children='ZTvar'),
    dcc.Slider(
        id= "ZTvar",
        min = 1,
        max = 50,
        value = 40,
    ),
    html.H3(children='XCvar'),
    dcc.Slider(
        id= "XCvar",
        min = 500,
        max = 1000,
        value = 700,
    ),
    html.H3(children='YCvar'),
    dcc.Slider(
        id= "YCvar",
        min = 100,
        max = 150,
        value = 120,
    ),
    html.H3(children='ZCvar'),
    dcc.Slider(
        id= "ZCvar",
        min = 100,
        max = 150,
        value = 120,
    )
])
@app.callback(
    Output(component_id='Tsai', component_property='figure'),
    Input(component_id='XTvar', component_property='value'),
    Input(component_id='YTvar', component_property='value'),
    Input(component_id='ZTvar', component_property='value'),
    Input(component_id='XCvar', component_property='value'),
    Input(component_id='YCvar', component_property='value'),
    Input(component_id='ZCvar', component_property='value')
)
def updatefigure(XTvar, YTvar, ZTvar, XCvar, YCvar, ZCvar):
    df = zip(s_out(XTvar, YTvar, ZTvar, XCvar, YCvar, ZCvar))
    fig = px.scatter(df,s1, s2)
    return fig

if __name__ == '__main__':
    app.run_server(debug=True)

Here you can see what is happening if i move one of the sliders.

Initial State

After slider movement

I appreciate every kind of help and i hope the problem is well described.


Solution

  • Your logic in your dash callback is incomplete.

    If you take a look at s1, s2 after you move your slider, you can find their length is increasing by 3600 every time you move your slider, since you never clear s1, s2 after each call to the callback.

    Therefore everytime you move your slider, you are drawing a new eclipse by appending new values to s1, s2!

    enter image description here

    Here are some advises to your code, to avoid this behaviour.

    1. Avoid defining global variables like s1, s2 = s_out(XTvar, YTvar, ZTvar, XCvar, YCvar, ZCvar) in your code. Global variables is a cache in your Dash app, and its value persist until you kill your debugging session. We have little control to them in Dash. See Dash Documentation for details. If you need to cache some values between callbacks, use dcc.Store

    2. Use Dash built-in debugger to see what is inside the callbacks. It could be useful to trace more complex callbacks.