How to get the current dataframe from animate_frame?

Hi everyone,

I would like to get the current value of a animation frame and then to print it in my python terminal but also to show it in the website, how can I do that ?

I already tried to output it a html.Div but it dosent work. I got this error:

Property “animation_frame” was used with component ID: “graph-pos” in one of the Input items of a callback. This ID is assigned to a dash_core_components.Graph component in the layout, which does not support this property. This ID was used in the callback(s) for Output(s): var.children

Hey @Zic, welcome to the forums.

Is that what you are referring to?

Yes and no. The goal is the same to this topic, but I want to get it from the current frame of the animate frame. I created this little code, so you can see what I am trying to do.

When I run this, I get this error :
Property “value” was used with component ID:
“myfig”
in one of the Input items of a callback.
This ID is assigned to a dash_core_components.Graph component
in the layout, which does not support this property.
This ID was used in the callback(s) for Output(s):
toShow.children

from dash import *
import pandas as pd
import plotly.express as px
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template
data = {

    "x": [1,2,3,4,5],
    "y": [1,2,3,4,5],
    "time": [1,2,3,4,5]

}

df = pd.DataFrame(data)

app = Dash(external_stylesheets=[dbc.themes.SLATE])
app.layout = html.Div([
    html.Div(
        className="app-header",
        children=[
            html.H1('Overview of the DashBoard', className="app-header--title"),
            dcc.Graph(id ="myfig",figure = px.scatter(df, x='x', y='y',  animation_frame="time", range_x=[0,5], range_y=[0,5])),
            html.Div(id="toShow", children=[])
        ]
    )])

@app.callback(
    Output("toShow", "children"),
    Input("myfig", "value"),
)
def getFrame(value):
    print(value)
    return value

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

I think if this is possible, it’ll have to be done client side as the animation_frame is not exposed to the dcc.Graph() (not sure if this is the right terminology).

Is animating the figure using dash an option?

I have to use Dash, my goal is to do a dashboard.

I also tried to use another method, I tried to use a dcc slider, but it only works for few data and my df have a lot of data so I got a ‘error loading layout’ :confused:

Hello @Zic ,

Here, check this out:

from dash import *
import pandas as pd
import plotly.express as px
import dash_bootstrap_components as dbc

import json
data = {

    "x": [1,2,3,4,5],
    "y": [1,2,3,4,5],
    "time": [1,2,3,4,5]

}

df = pd.DataFrame(data)

app = Dash(external_stylesheets=[dbc.themes.SLATE])
app.layout = html.Div([
    html.Div(
        className="app-header",
        children=[
            html.H1('Overview of the DashBoard', className="app-header--title"),
            html.Button(id='syncData', style={'display': 'none'}),
            dcc.Graph(id ="myfig",figure = px.scatter(df, x='x', y='y',  animation_frame="time", range_x=[0,5], range_y=[0,5])),
            dcc.Store(id='currentFrame', storage_type='local', data=0),
            html.Div(id='toShow')
        ]
    )])

app.clientside_callback(
    """
        async function (graph, target) {
            var myGraph = document.querySelector(`#${graph} .js-plotly-plot`)
            const delay = ms => new Promise(res => setTimeout(res, ms));
            while (!myGraph) {
                await delay(100)
                myGraph = document.querySelector(`#${graph} .js-plotly-plot`)
            }
            myGraph.on('plotly_animated', () => {
                localStorage.setItem(target, myGraph.layout.sliders[0].active)
                document.querySelector('#syncData').click()
            })
            return window.dash_clientside.no_update
        }
    """,
    Output("currentFrame", "id"),
    Input("myfig", "id"),
    State("currentFrame", "id"),
)

app.clientside_callback(
    """
        function (n, store) {
            return localStorage.getItem(store)
        }
    """,
    Output('currentFrame', 'data'),
    Input('syncData', 'n_clicks'),
    State("currentFrame", "id"),
    prevent_initial_call=True
)

@app.callback(
    Output('toShow', 'children'),
    Input('currentFrame', 'data'),
    State("myfig", "figure"),
)
def toShow(d, fig):
    return html.Div([
        d,
        '-- data --',
        json.dumps(fig['frames'][int(d)])
    ], style={'padding': '10px'})

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

This adds a custom event listener on the underlying plotly div, this will trigger and pull the data based upon the current frame when the animation is stopped. :slight_smile:

The other callbacks are all to sync the data… Hopefully soon, Dash will allow JS functions to update the properties directly.

2 Likes

Amazing, Thank you !!!

1 Like