Live graph controlled with an interval

I have troubles updating this graph. I don’t know why the axis are not updating and the deque list is not working properly which causes that i obtain this graph

df=pd.DataFrame()
df['patient']= [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
                3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
                4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4]
df['heart rate']=np.random.uniform(low=50, high=100, size=80)
df['respiratory rate']=np.random.uniform(low=20,high=70, size=80)
df['temperature']=np.random.uniform(low=35.7,high=40, size=80)
df['oxygen saturation']=np.random.uniform(low=80,high=100,size=80)
df['physiology']=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
                  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
df['systolic blood pressure']=np.random.uniform(low=55,high=120,size=80)
df['diastolic blood pressure']=np.random.uniform(low=30, high=95,size=80)
df['bedID']= [6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
              4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
              3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7]
df['age']=[12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
           4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
           8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
df['score']=""
rng = pd.date_range('2015-02-24', periods=80, freq='h')
df['datetime']=rng
patient_id=pd.unique(df['patient'])

f=deque()
g=deque()
@app.callback(
    Output('live-update4','children'),
    [Input('drop56','value'),
    Input('graph_interval4','n_intervals')])

def graph_dynamic(variables8, interval):
    dff=0
    if variables8 is None:
            raise dash.exceptions.PreventUpdate()
    else:
        dff=0
        ff=f
        gg=g
        dff=df
        dff=nuevoRegistro(dff,1)
        ff.extend(np.array(dff.loc[dff['patient']==1][str(variables8)]))
        gg.extend(dff.query('patient==1')['datetime'])
        traces=go.Scatter(x=list(gg), y=list(ff), mode='lines+markers')#append
        layout=go.Layout(xaxis=dict(range=[min(gg),max(gg)]),yaxis=dict(range=[min(ff),max(ff)]))


        
    return dcc.Graph(figure=go.Figure(data=traces, layout=layout)
        ,style={'width':'81vh', 'height':'4', 'display':'inline-block'},animate=False)
def nuevoRegistro(df, paciente):

    physiology = df.loc[df['patient']==paciente]['physiology'].values[-1]
    bedID = df.loc[df['patient']==paciente]['bedID'].values[-1]
    age = df.loc[df['patient']==paciente]['age'].values[-1]


    score = df.loc[df['patient']==paciente]['score'].values[-1]


    HR = np.random.uniform(low=50, high=100, size=1)
    RR = np.random.uniform(low=20,high=70, size=1)
    Temp = np.random.uniform(low=35.7,high=40, size=1)
    OxS = np.random.uniform(low=80,high=100,size=1)
    SBP = np.random.uniform(low=55,high=120,size=1)
    DBP = np.random.uniform(low=30, high=95,size=1)


    datetime = df.loc[df['patient']==paciente]['datetime'].values[-1] + pd.Timedelta(1, 'h')


    df_aux = pd.DataFrame([[paciente,  HR[0], RR[0],Temp[0], OxS[0], physiology, SBP[0], DBP[0], bedID, age, score, datetime]],
                        columns= df.columns
                        )


    df = df.append(df_aux, ignore_index=True)

    return df

Hi,

I suspect that the graph is not updated because ff and gg aren’t persisting updates at every callback execution (they are overwritten by f and g. Besides, when lines like this appears in line plots, it is usually because the data is not sorted by x values (see here), although this does not seem to be the problem in your case (it could be worth checking).

That said, I would encourage to take a look on the extendData parameter in dcc.Graph. In a nutshell, this parameter allow you to append just the new data to the traces, instead of creating an entire new Plotly figure after appending a row to the dataframe. It can be a bit difficult to figure out what you need to return in the callback, but this will make your callback much more efficient and less cluttered.

You can read more about extendData in the component reference. Otherwise, I would be happy to help you with this particular case.

1 Like

Thank you very much! I will try to use extendData, I am having some troubles to implement it.
Moreover, I have change ff and gg in order not to be overwritten but the result is the same and also sorting the values but they were already sorted.

Could you share how traces looks like just before the return statement in the callback? I believe you are pushing the entire dataframe again to ff and gg, instead of just the new row, so there might be some duplicated values.

Finally I could solved it by putting global df and deleting ff and gg. Thank you very much for your time!

Just for reference it should be noted that it is generally not recommended to use global variables unless that are constant (and read-only).

Thank you for your advice, that is why in first place i was not using global. However, I could not solve it in any other way.