Python DASH chart glitch on update? - python

I want to create a graphical terminal like a tradingview. For this, I use plotly dash to make the display as comfortable as possible. But a situation arose that I have been unable to resolve for several days now.
Now my code looks like this:
import asyncio import datetime as DT from threading import Thread
import dash import numpy as np import plotly.graph_objs as go from dash import dcc, html from dash.dependencies import Input, Output
# ======================================================================================================================
# === Create DATA ======================================================================================================
# ======================================================================================================================
Start_Time = DT.datetime.timestamp(DT.datetime.now().replace(second=0, microsecond=0)) * 1000 X_time = np.array([]) Y_one = np.array([]) Y_two = np.array([]) Y_three = np.array([])
async def create_connection():
from random import randrange
import time
count = 0
global X_time
global Y_one
global Y_two
global Y_three
while count < 1000000:
X_time = np.append(X_time, count)
Y_one = np.append(Y_one, randrange(10000))
Y_two = np.append(Y_two, randrange(10000))
Y_three = np.append(Y_three, randrange(10000))
count += 1
time.sleep(1)
def async_main_wrapper():
"""Not async Wrapper around async_main to run it as target function of Thread"""
asyncio.run(create_connection())
# ======================================================================================================================
# === Create DASH ======================================================================================================
# ======================================================================================================================
X = np.array([0]) Y = np.array([0])
external_stylesheets = ['https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght#400;600&display=swap'] app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
colors = {
'background': '#FDFEFE',
'text': '#424242' }
app.layout = html.Div(style={'backgroundColor': colors['background']}, children=[
html.H1(
children='Main graph',
style={
'textAlign': 'left',
"fontFamily": "Montserrat Alternates",
"fontWeight": "600",
'color': colors['text']
}),
dcc.Graph(id='live_graph', style={'height': '700px', 'width': '100%'}, animate=True, config={'scrollZoom':True}),
dcc.Interval(
id='graph_update',
interval=1000 * 1
), ] )
def create_area(line_Y_one, line_Y_two, line_Y_three, X_time):
fig = {'data': [line_Y_one, line_Y_two, line_Y_three],
'layout': go.Layout(xaxis=dict(range=[min(X_time), max(X_time)], rangeslider=dict(visible=True)),
yaxis=dict(tickfont=dict(color='rgba(0, 188, 212, 0.0)')),
yaxis2=dict(overlaying="y", tickfont=dict(color='rgba(0, 188, 212, 0.0)')),
yaxis3=dict(overlaying="y"),
)}
return fig
#app.callback(Output('live_graph', 'figure'),
Input('graph_update', 'n_intervals')) def update_graph_scatter(graph_update):
global X_time
global Y_one
global Y_two
global Y_three
clr_green = 'rgba(139, 195, 74, '
clr_red = 'rgba(220, 20, 60, '
clr_brown = 'rgba(93, 64, 55, 1.0)'
line_Y_one = go.Scatter(
x=X_time,
y=Y_one,
name='Y_one',
line=dict(color=clr_green + '0.0)'),
fillcolor=clr_green + '0.3)',
fill='tozeroy',
yaxis='y1'
)
line_Y_two = go.Scatter(
x=X_time,
y=Y_two,
name='Y_two',
line=dict(color=clr_red + '0.0)'),
fillcolor=clr_red + '0.3)',
fill='tozeroy',
yaxis='y1'
)
line_Y_three = go.Scatter(
name='Y_three',
x=X_time,
y=Y_three,
line=dict(color=clr_brown),
yaxis='y3'
)
return create_area(line_Y_one, line_Y_two, line_Y_three, X_time)
# ======================================================================================================================
# === Start ===========================================================================================================
# ======================================================================================================================
if __name__ == '__main__':
th = Thread(target=async_main_wrapper)
th.start()
app.run_server(host='localhost', port=8080, debug=True, use_reloader=False)
th.join()
When starting the graph, everything goes well, it is updated once a second, as specified in the settings:
https://i.postimg.cc/L8yCj6Dw/normal.gif
But if I switch to another tab or window (i.e. I don't look at the chart), then when I return, the chart starts to update quickly, compressing and decompressing like a spring:
https://i.postimg.cc/BvXhp9w6/glitch.gif
How can I solve this situation?
And as an addition: could you recommend a good raftly dash guide that
will show solutions to similar problems?

Related

Not able to render charts using plotly and python dash

I created a dash app to render some real time charts using plotly.objs. All the data is being created in the database so it's not like the charts are empty.
The page where the dash app renders the charts is blank. It does not show any errors even in debug mode.The complete code is given below:
import dash
from dash import html,dcc
from dash.dependencies import Output, Input
import plotly
import random
import plotly.graph_objs as go
# from collections import deque
import datetime
from plotly.subplots import make_subplots
from pymongo import MongoClient
# from time import ctime
import time
from math import ceil
from configparser import ConfigParser
from waitress import serve
todays_date = str(datetime.datetime.today().date())
config = ConfigParser()
configfile = 'config.ini'
config.read(configfile)
try:
host = config['server']['host']
port = int(config['server']['port'])
mhost = config['mongo']['host']
mport = int(config['mongo']['port'])
muser = config['mongo']['user']
mpass = config['mongo']['pass']
except Exception as e:
print(f'Error in taking config values: {e}')
app = dash.Dash(__name__)
conn = MongoClient(host=mhost,port=mport,username=muser,password=mpass)
db = conn['GraphData']
collec = db[todays_date]
app = dash.Dash(__name__,title='IV Graphs',update_title='Plotting...')
app.layout = html.Div(
[
html.Div(children=html.Div(id='live-graph'), className='row'),
dcc.Interval(
id = 'graph-update',
interval = 5000,
n_intervals = 0
),
]
)
#app.callback(
Output('live-graph', 'children'),
[ Input('graph-update', 'n_intervals') ]
)
def update_graph_scatter(n):
colLimit = 2
plotData = list(collec.find())#{'$and':[{'title':{'$ne':'AD BN'}},{'title':{'$ne':'AD N'}}]}))
# print(plotData)
titleList = []
reqOrder = ['AD N','AD BN','NIFTY CALL WEEKLY IV', 'BANKNIFTY CALL WEEKLY IV',
'NIFTY PUT WEEKLY IV', 'BANKNIFTY PUT WEEKLY IV',
'NIFTY CALL MONTHLY IV', 'BANKNIFTY CALL MONTHLY IV',
'NIFTY PUT MONTHLY IV', 'BANKNIFTY PUT MONTHLY IV', 'PCR CURRENT N',
'PCR CURRENT BN','PCR NEXT N','PCR NEXT BN']
for titleData in reqOrder:
for dbData in plotData:
if dbData['title'] == titleData:
if titleData == 'AD BN' or titleData == 'AD N':
titleList.append(f"{dbData['title']}: {dbData['ratio']} UP: {dbData['up']} DOWN: {dbData['down']}")
break
else:
titleList.append(dbData['title'] + ": "+ str(round(float(dbData['yaxis'][-1]),2)))
print(titleList)
fig = make_subplots(rows=ceil(len(reqOrder)/colLimit), cols=colLimit,
subplot_titles=tuple(titleList),
)
colNum = 1
rowNum = 1
graphs = []
LAYOUT = {
'plot_bgcolor': 'white',
'paper_bgcolor': 'white'
}
fig['layout'].update(LAYOUT)
for algo in reqOrder:
for dbData in plotData:
if dbData['title'] == algo:
xData = convertTimeStamps(dbData['xaxis'])
yData = convertToFloat(dbData['yaxis'])
if colNum>colLimit:
colNum = 1
rowNum+=1
# print([0 for i in plotData[dbData].keys()])
fig.add_trace(
go.Scatter(mode ="lines",
x=xData, y=yData),
row=rowNum, col=colNum
)
if dbData['title'] == 'AD BN' or dbData['title'] == 'AD N':
# fig.add_hline(y=0)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[2 for i in xData]),
row=rowNum, col=colNum
)
fig.add_trace(
go.Scatter( mode = 'lines',line = dict(dash = 'longdash'),x=xData,
y=[0.5 for i in xData]),
row=rowNum, col=colNum
)
colNum+=1
# break
fig.update_layout(
autosize = True
)
print(fig)
graphs.append(html.Div(style={
'display': 'flex',
'flex-flow': 'column',
'background-color': 'green',
'height': '200vh',
'width': '100%'
},children = [ dcc.Graph(
id='basic-interactions',
figure=fig,
style={'height': '100%'}
)]))
return graphs
def convertTimeStamps(epochList):
ans = []
for timeStamp in epochList:
ans.append(datetime.datetime.fromtimestamp(timeStamp))
return ans
def convertToFloat(data):
ans = []
for p in data:
ans.append(float(p))
return ans
if __name__ == '__main__':
app.run_server(host=host, port=port,debug = False)
I tried to restart the page and even the system. What is wrong here?

Using complex numpy arrays with DCC.Store component (Dash/Python)

so I am working with relatively large arrays (size (13, 8192)) to plot some Figures on a website. It has already been implemented like this, so changes are difficult to make.
As I am running out of memory using the local storage of the browser, I have to use directly a given complex NumPy array and then split it into the real and imaginary parts in another Callback. The problem is that I can't JSON serialize complex-like arrays. Does someone know what can I do to "save" this sort of array using the dcc.Store component of Dash? Thanks in advance.
Here is an example of the code (it is a really short version of it).
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import numpy as np
app = dash.Dash(__name__)
T0 = 1E-12 # duration of input
N = 8192 # number of points
dt = 750*T0/N
T = np.arange(-N/2, N/2)*dt
m = 1
C = 0
def envelopef(T,T0,C,m):
U = (np.exp(-((1+1j*C)/2)*((T/T0)**(2*m)))).astype(complex)
UI = np.absolute(U)**2
return U, UI
z = np.arange(-10,10)
U, UI = envelopef(T,T0,C,m)
scatter1 = go.Scatter(x=T/T0,y=UI)
figure1 = go.Figure(data=[scatter1]).update_layout( )
env_graph = dcc.Graph(id='envelopesss',
animate=True,
figure=figure1.update_layout(width=600, height=600,
xaxis = dict(range = [-8, 8])))
M_slider = dcc.Slider(
id='m_slider',
min=1,
max=10,
step=1,
value=m,
marks={
1: {'label': '1'},
10: {'label': '10'}},
)
app.layout = html.Div([
M_slider,
dcc.Store(id='session', storage_type='local'),
dcc.Loading(id="loading1",children=[html.Div([env_graph]) ],type="circle",),
])
#app.callback(
Output("loading1", "children"),
Output("session", "data"),
[Input("m_slider", "value")])
def update_bar_chart(mn):
U, UI = envelopef(T,T0,C,mn)
phase = np.angle(U)
scatter1 = go.Scatter(x=T/T0,y=UI)
figure1 = go.Figure(data=[scatter1]).update_layout(width=600, height=600,
xaxis = dict(range = [-8, 8]))
data = {'u': U , 'ui':UI, 'up': phase}
env_graph = dcc.Graph(figure=figure1)
return env_graph, data
app.run_server(debug=True)
You might want to take a look at the ServersideOutput component from dash-extensions. It keeps the data server side (which should improve the performance of your app), and since the default serializer is pickle, complex-valued arrays work out of the box. You can install it via pip,
pip install dash-extensions==0.0.66
To enable use of serverside outputs, replace the app initialization code by
from dash_extensions.enrich import DashProxy, html, dcc, Input, Output, ServersideOutput, ServersideOutputTransform
app = DashProxy(__name__, transforms=[ServersideOutputTransform()])
Next, replace the Output by a ServersideOutput,
#app.callback(
Output("loading1", "children"),
ServersideOutput("session", "data"),
[Input("m_slider", "value")])
That's it. Your app should now work. For completeness, here is the full app code,
import plotly.graph_objects as go
import numpy as np
from dash_extensions.enrich import DashProxy, html, dcc, Input, Output, ServersideOutput, ServersideOutputTransform
app = DashProxy(__name__, transforms=[ServersideOutputTransform()])
T0 = 1E-12 # duration of input
N = 8192 # number of points
dt = 750 * T0 / N
T = np.arange(-N / 2, N / 2) * dt
m = 1
C = 0
def envelopef(T, T0, C, m):
U = (np.exp(-((1 + 1j * C) / 2) * ((T / T0) ** (2 * m)))).astype(complex)
UI = np.absolute(U) ** 2
return U, UI
z = np.arange(-10, 10)
U, UI = envelopef(T, T0, C, m)
scatter1 = go.Scatter(x=T / T0, y=UI)
figure1 = go.Figure(data=[scatter1]).update_layout()
env_graph = dcc.Graph(id='envelopesss',
animate=True,
figure=figure1.update_layout(width=600, height=600,
xaxis=dict(range=[-8, 8])))
M_slider = dcc.Slider(
id='m_slider',
min=1,
max=10,
step=1,
value=m,
marks={
1: {'label': '1'},
10: {'label': '10'}},
)
app.layout = html.Div([
M_slider,
dcc.Store(id='session', storage_type='local'),
dcc.Loading(id="loading1", children=[html.Div([env_graph])], type="circle", ),
])
#app.callback(
Output("loading1", "children"),
ServersideOutput("session", "data"),
[Input("m_slider", "value")])
def update_bar_chart(mn):
U, UI = envelopef(T, T0, C, mn)
phase = np.angle(U)
scatter1 = go.Scatter(x=T / T0, y=UI)
figure1 = go.Figure(data=[scatter1]).update_layout(width=600, height=600,
xaxis=dict(range=[-8, 8]))
data = {'u': U, 'ui': UI, 'up': phase}
env_graph = dcc.Graph(figure=figure1)
return env_graph, data
app.run_server(port=7777)

How to not show default dcc.graph template in Dash?

I am trying not the show the defult dcc.graph when the app runs. I just want to show my graph when app runs
Here is my code,
App layout
dbc.Row([
dbc.Col([
dcc.Graph(id='datatable-upload-graph', responsive=True, style={
'display': 'block'
})
], xs=10, sm=8, md=5, lg=6, xl=5)
])
Callbacks and methods
#app.callback(
Output('datatable-upload-graph', 'figure'),
Input('container-datatable', 'data')
)
def display_gantt(container_datatable):
df = pd.DataFrame(container_datatable)
df['Start Date'] = pd.to_datetime(df['Start Date'], errors='coerce')
df['End Date'] = pd.to_datetime(df['End Date'], errors='coerce')
fig = px.timeline(df, x_start="Start Date", x_end="End Date", y="Project Name", color="Status")
fig.update_yaxes(autorange="reversed")
if container_datatable is None:
return []
else:
return fig
app.config['suppress_callback_exceptions'] = True
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
The essence:
Just make sure to not leave the figure attribute of dcc.Graph unspecified, but rather, for example, like this:
dcc.Graph(id='datatable-upload-graph', figure = blank_figure())
Where blank_figure() is a figure that is not only empty like in the default version, but stripped of all visible features.
The details:
In your app layout you've set up your dcc.Graph as:
dcc.Graph(id='datatable-upload-graph', responsive=True, style={
'display': 'block'
})
What you're missing here is a specification for the figure attribute. Your app will work perfectly fine without it, but you will end up with that empty figure until you've managed to populate the figure object through one of your callbacks. And for longer loading times the empty figure will become visible.
But you can remedy this by specifying a completely blank figure like:
dcc.Graph(id='datatable-upload-graph', figure = blank_figure())
where blank_figure() is this:
def blank_fig():
fig = go.Figure(go.Scatter(x=[], y = []))
fig.update_layout(template = None)
fig.update_xaxes(showgrid = False, showticklabels = False, zeroline=False)
fig.update_yaxes(showgrid = False, showticklabels = False, zeroline=False)
return fig
The code snippet below will let you test this with a random data sample. The app itself is pretty neat as well (in all modesty). Nothing too fancy, but it will let you check out some templates available for your figures through fig.update_layout(template = <template>)
Without including figure = blank_figure() in dcc.Graph, the app will look like this for a brief moment:
And with figure = blank_figure() the app will look like this:
And when the simulations have come to an end the app will look like this:
And now you can easily take a look at how the figure will look like using the different templates, like 'plotly_dark':
Just switch between commenting out these two lines to see the effects in the complete snippet below.
dcc.Graph(id="graph", figure = blank_fig())
# dcc.Graph(id="graph")
Complete code:
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from jupyter_dash import JupyterDash
from dash.dependencies import Input, Output
templates = ['plotly', 'seaborn', 'simple_white', 'ggplot2',
'plotly_white', 'plotly_dark', 'presentation', 'xgridoff',
'ygridoff', 'gridon', 'none']
def blank_fig():
fig = go.Figure(go.Scatter(x=[], y = []))
fig.update_layout(template = None)
fig.update_xaxes(showgrid = False, showticklabels = False, zeroline=False)
fig.update_yaxes(showgrid = False, showticklabels = False, zeroline=False)
return fig
# startfig = blank_fig()
# Dash
app = JupyterDash(__name__)
app.layout = html.Div([
dcc.RadioItems(
id='template_radio',
options=[{'label': k, 'value': k} for k in templates],
value=templates[0]
),
html.Hr(),
html.Div(id='display_templates'),
dcc.Graph(id="graph", figure = blank_fig())
# dcc.Graph(id="graph")
])
# Make a figure with selected template
#app.callback(Output('graph', 'figure'),
[Input('template_radio', 'value')])
def make_graph(template):
np.random.seed(1)
start = 2021
ncols = 50
nrows = 100
cols = [str(i) for i in np.arange(start, start+ncols)]
df = pd.DataFrame(np.random.randint(-2,3, (nrows,ncols)), columns = cols).cumsum()
df.iloc[0] = 0
# figure
fig = px.line(df, x=df.index, y=cols)
fig.update_layout(template = template)
return fig
app.run_server(mode='inline', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)

TypeError: update_graph_scatter() takes 0 positional arguments but 1 was given

TypeError: update_graph_scatter() takes 0 positional arguments but 1 was given
Getting the above error while using dash with python.
Below is my code.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import requests
app = dash.Dash()
app.layout = html.Div([
html.Div([
html.Iframe(src = 'https://www.flightradar24.com', height = 500, width = 1200)
]),
html.Div([
html.Pre(
id='counter_text',
children='Active flights worldwide:'
),
dcc.Graph(id='live-update-graph',style={'width':1200}),
dcc.Interval(
id='interval-component',
interval=6000, # 6000 milliseconds = 6 seconds
n_intervals=0
)])
])
counter_list = []
#app.callback(Output('counter_text', 'children'),
[Input('interval-component', 'n_intervals')])
#staticmethod
def update_layout(n):
url = "https://data-live.flightradar24.com/zones/fcgi/feed.js?faa=1\
&mlat=1&flarm=1&adsb=1&gnd=1&air=1&vehicles=1&estimated=1&stats=1"
# A fake header is necessary to access the site:
res = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
data = res.json()
counter = 0
for element in data["stats"]["total"]:
counter += data["stats"]["total"][element]
counter_list.append(counter)
return 'Active flights worldwide: {}'.format(counter)
#app.callback(Output('live-update-graph','figure'),
[Input('interval-component', 'n_intervals')])
def update_graph(n):
fig = go.Figure(
data = [go.Scatter(
x = list(range(len(counter_list))),
y = counter_list,
mode='lines+markers'
)])
return fig
if __name__ == '__main__':
app.run_server()
As you can see in the browser i am getting this issue.
Please help as
i have tried every solution to no avail
The problem is the decorator, #staticmethod, here:
#app.callback(Output('counter_text', 'children'),
[Input('interval-component', 'n_intervals')])
#staticmethod
def update_layout(n):
url = "https://data-live.flightradar24.com/zones/fcgi/feed.js?faa=1\
&mlat=1&flarm=1&adsb=1&gnd=1&air=1&vehicles=1&estimated=1&stats=1"
This is a normal function, not a method of a class, so the #staticmethod decorator is incorrect here. I removed that, and your app worked nicely.

Dash graph does not display

I am trying to make a graph with Dash. When I copy the examples in Plotly it works fine, but when I change some variables with my values and run it then all the elements appear except for the graph.
This is the code:
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=subset_date['Year'].unique().min(),
max=subset_date['Year'].unique().max(),
value=subset_date['Year'].unique().min(),
step=None
)
])
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('year-slider', 'value')])
def update_figure(selected_year):
return {
'data': go.Scatter(x=subset_date.index,
y=subset_date['Value'],
mode='lines'),
'layout': go.Layout(
title='My Title'
)
}
if __name__=='__main__':
app.run_server()
What am I doing wrong?
Here is a simple app layout:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
# Scimago Journal & Country Rank
# from www.scimagojr.com
st = {'Date': ['2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01', '2015-01-01', '2016-01-01','2017-01-01', '2018-01-01'],
# 'Turkey': [26526, 30839, 33325, 34926, 36766, 40302, 41400, 44529, 47138, 44584,45582],
'Iran': [20006, 24509, 30013, 39682, 41513, 42252, 44923, 45013, 52538, 56029, 60268]
}
st = pd.DataFrame(st)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01', '2015-01-01', '2016-01-01','2017-01-01', '2018-01-01']
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['Iran'],
name = 'Iran',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Scimago Journal & Country Rank (Iran)',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# range slider
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 11)},
min = 0,
max = 10,
value = [1, 7])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[
Input('slider', 'value')])
def update_figure( input2):
# filtering the data
st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['Iran'],
name = 'Iran',
# mode = 'markers'
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
fig = go.Figure(data = [trace_1], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = False)

Categories

Resources