I'm designing a Dash web application which takes in data from the backend. The backend consists of reading files (in the past day) that are mounted onto a RHEL directory with an ETL process (a python script that runs at 4am everyday). I have already designed a process to read in files and display them in graphs. However, I'm looking for ways to refresh the dash application whenever files are uploaded to the directory-basically updating my data everyday or every half day. I realize I will have to do a Polling mechanism or something of the sort. So I started looking into the dcc.interval component of Dash.
Currently, I hardcode a date of August 31 and want to refresh data every 20seconds until September 6th. I defined a function which takes in a date, in this range, and returns a dataframe as an output (after reading in files). From there, whenever my interval function is called, I want to update the graphs.
My layout (basically I have 9 graphs, 2 dropdowns, and 1 dcc interval). The dropdowns are meant to update the data based on user selection (if user selects a province, show only that province data):
firstdate='2022-08-31'
df=collectData(firstdate)
app.layout = html.Div([
html.H1("Netstat Data Analytics Dashboard"),
html.Div(id='output_container', children=[]),
html.Br(),
dcc.Dropdown(
id='provinces',
options=createDropdownProvinces(df),
value='All Provinces'
),
dcc.Dropdown(
id='my-input',
options=createDropdown(df)
),
dcc.Interval(
id='interval-component',
interval=1*20000, #every 5 ms,
n_intervals=0
),
html.Div(id='live-update-text'),
html.H3("Metric - Acc_InitialERabEstabSuccRate"),
dcc.Graph(id='my_graph', figure=fig),
...more dcc graphs...
])
My callback function:
#Since I need to update ALL graphs depending on 3 inputs: (i) If I invoke a refresh, (ii) if the user selects a province -Dropdown1, or (iii) if a user selects a NodeId - Dropdown2
@app.callback(
Output('my_graph', 'figure'),
Output('my_graph2', 'figure'),
#... more Output graphs (in total I have 9 graphs)
Input('interval-component', 'n_intervals'),
Input(component_id='provinces', component_property='value'),
Input(component_id='my-input', component_property='value')
)
def update_output_Province(intervals, inputValueProvinces, inputValueNode):
triggered_id=ctx.triggered_id
if triggered_id=='provinces': #If the user selects provinces
if inputValueProvinces!='All Provinces':
filtered_df=df[df['Province'] == inputValueProvinces]
else:
filtered_df=df
elif triggered_id=='my-input': #if user selects dropdown2
if inputValueNode!='All Nodes':
filtered_df=df[df['NodeId'] == inputValueNode]
else:
filtered_df=df
elif triggered_id=='interval-component': #if a refresh is requested
#update df
print(intervals)
newdate=datetime.strptime(firstdate, "%Y-%m-%d")
newdate+=timedelta(days=intervals) #add number of intervals as days to update data collection
print(newdate) #for error debugging
df=collectData(str(newdate.date()))
print(df)
filtered_df=df.copy()
fig=px.scatter(filtered_df, x='Time', y='Acc_InitialERabEstabSuccRate', color='NodeId', hover_name='NodeId')
fig2=px.scatter(filtered_df, x='Time', y='Int_DlThroughput_kbps', color='NodeId', hover_name='NodeId')
return fig, fig2, fig3, etc...
The problem with this code is the FIRST time that the interval_component is called it's value is 19, I don't understand why, shouldn't it be 1,2,3,4 and so on every 20 seconds? Since my dataframe is unable to collect data beyond September 6th, it returns an empty dataframe and I receive errors. Any suggestions?