Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
524 views
in Technique[技术] by (71.8m points)

Real-time plotly-dash graph from python script

I am trying to create a real-time dash graph using plotly. I am following this tutorial link with the difference that I would like to update the data from another part of the script. In other words, I would like to have my script running and collecting data and then in real time it should be shown on the graph.

This is what I have so far

import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
import plotly
import random
import plotly.graph_objs as go
from collections import deque
import pandas as pd


class Plot:

    def __init__(self):
        self.points=[]
        self.app = dash.Dash(__name__)
        self.app.layout = html.Div(
            [
                dcc.Graph(id='live-graph', animate=True),
                dcc.Interval(
                    id='graph-update',
                    interval=500
                ),
            ]
        )
        self. app.callback(Output('live-graph', 'figure'),
        [Input('graph-update', 'n_intervals')])(self.update_graph_scatter)
        
    def start_server(self):
        self.app.run_server(debug=True,host='127.0.0.1', port=8011)

    def update_graph_scatter(self):
        
        pos = pd.DataFrame(data=self.points, columns=['x', 'y'])

        data = plotly.graph_objs.Scatter(
                x=pos['x'],
                y=pos['y'],
                name='Scatter',
                mode= 'lines+markers'
                )

        return {'data': [data],'layout' : go.Layout(xaxis=dict(range=[min(pos['x']),max(pos['x'])]),
                                                    yaxis=dict(range=[min(pos['y']),max(pos['y'])]),)}

    def add_point(self,point):
        self.points.append(point)
    

What I want is doing something like :

plot=Plot()
plot.start_server()

for i in data_from_my_sensor_callback:
    plot.add_point(i)

But after start_server() the script is not executed. I also tried to run it in a separate thread but the result is the same.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To my knowledge, there are presently no official Dash components that support real-time updates initiated from the server, which seems to be what you are after (the Interval component initiates the update from the client). One possible solution would be to use a websocket, which is the approach used by the WebSocket component from dash-extensions. Here is a small example,

import json
import dash_html_components as html
import random
from gevent import sleep
from dash import Dash
from dash.dependencies import Input, Output
from dash_extensions import WebSocket
from dash_extensions.websockets import SocketPool, run_server


# Generator to simulate continuous readings from sensor.
def query_sensor():
    while True:
        sleep(random.uniform(0, 20))  # delay between sensor readings
        yield random.uniform(0, 1)  # the sensor value


# This block runs asynchronously.
def ws_handler(ws):
    for i in query_sensor():
        ws.send(json.dumps(i))  # send data


# Create example app.
app = Dash(prevent_initial_callbacks=True)
socket_pool = SocketPool(app, handler=ws_handler)
app.layout = html.Div([html.Div(id="data"), WebSocket(id="ws")])


@app.callback(Output("data", "children"), [Input("ws", "message")])
def update_data(msg):
    return json.dumps(msg["data"])


if __name__ == '__main__':
    run_server(app, port=5000)  # 5000 if the default port

tested with dash-extensions==0.0.41. Disclaimer: I am the author of dash-extensions.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...