Plotly Dash. How to relayout the x axis of the graph so that it's not looks crowded?

I have this existing code that can update and extend the data in a scatter graph, looks like this.
image
I want to relayout the xaxis of the graph with range of maximum of 9 data so that the lines will not be crowded, like this.
image

app.layout = html.Div([
    html.Div(style={'display': 'flex'}, children=[
        dcc.Graph(
            id='graph-ph',
             figure={
                 'data': [
                     {'x':  [],
                      'y': [0, random.random()],
                      'mode':'lines+markers',
                      }],
                 'layout': {
                     'title': 'pH (pH)'
                 }},
             ),
]),
    dcc.Interval(
        id='interval-graph-update',
        interval=1000,
        n_intervals=0),
])
@app.callback(Output('graph-ph', 'extendData'),
              [Input('interval-graph-update', 'n_intervals')],
              [State('graph-ph', 'figure'),
               ])
def update_extend_traces_traceselect(n_intervals, existing):
    trace_selection = 0
    x_new = datetime.datetime.now()
    y_new = random.random()
return dict(x=[[x_new]], y=[[y_new]]), [trace_selection]

Hi @Chrollo !

You just have to include in the output of your callback the maximum number of points that you want to see displayed on the plot at the same moment (9 in this example):

 return dict(x=[[x_new]], y=[[y_new]]), [trace_selection], 9

I hope this helps!

It’s not working ma’am @celia
image

x_new = datetime.datetime.now() 
y_new = random.random()
return dict(x=[[x_new]], y=[[y_new]]), 9

Did you try it without removing [trace_selection]?

@celia it’s working right now. It’s display only the recent 9 data but the previous data is being deleted.

Then I think the best option is to change the approach to update the data and re-render the whole figure. Try this:

from dash import Dash, dash_table, dcc, html, callback, Input, Output, State
from dash.dependencies import Input, Output
import pandas as pd
import random
import datetime
import plotly.graph_objects as go

app = Dash(__name__)

app.layout = html.Div([
    html.Div(style={'display': 'flex'}, children=[
        dcc.Graph(
            id='graph-ph',
             figure={
                 'data': [
                     {'x':  [],
                      'y': [0, random.random()],
                      'mode':'lines+markers',
                      }],
                 'layout': {
                     'title': 'pH (pH)'
                 }},
             ),
]),
    dcc.Interval(
        id='interval-graph-update',
        interval=1000,
        n_intervals=0),
])

@callback(
    Output('graph-ph', 'figure'),
    Input('interval-graph-update', 'n_intervals'),
    State('graph-ph', 'figure')
    )
def update_extend_traces_traceselect(n_intervals, fig_raw):
    x_new = datetime.datetime.now()
    y_new = random.random()

    fig_raw['data'][0]['x'] = fig_raw['data'][0]['x'] + [x_new]
    fig_raw['data'][0]['y'] = fig_raw['data'][0]['y'] + [y_new]

    fig = go.Figure(fig_raw)

    if len(fig_raw['data'][0]['x']) > 9 :
        fig.update_xaxes(range=[fig_raw['data'][0]['x'][-9], x_new+datetime.timedelta(seconds=1)], autorange=False)

    return go.Figure(fig)

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

Thank you it worked! I have last question how can I add a range slider? I tried adding fig.update_layout(xaxis={“rangeslider”: {“visible”: True}}) but I’m having an error says ‘Invalid property specified for object of type plotly.graph_objs.layout.xaxis.rangeslider.YAxis: ‘_template’’

The problem seems to come from the step where we recreate the figure from in fig = go.Figure(fig_raw), if the figure already has a range slider.

@alexcjohnson helped me solve this and already created a bug report :slight_smile: : rangeslider template bug · Issue #6310 · plotly/plotly.js · GitHub

The workaround is to add this bit of code:

    # add these lines before fig = go.Figure(fig_raw)
    if 'rangeslider' in fig_raw['layout']['xaxis']:
        del fig_raw['layout']['xaxis']['rangeslider']['yaxis']