Many thanks for your example, it does exactly what I need. However, I had no success in adapting your code to my app 
My app, when the buttons that I want to unfocus (or “redraw”) are clicked, they call a function named “label_data” which in turn calls a function named “next_data”, which somehow is not working as expected, and I cannot find why.
I attach here my working code, and also my attempt to “redraw” the button named “Normal”, in case you can take it a look.
Working code:
import os
import streamlit as st
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
st.session_state["username"] = "user"
# Set paths
basedir = os.getcwd()
flow_data = pd.read_csv(os.path.join(basedir, 'data/Flow.csv'))
paw_data = pd.read_csv(os.path.join(basedir, 'data/Paw.csv'))
last_index_file = os.path.join(basedir, f'{st.session_state["username"]}_last_index.txt')
labels_file = os.path.join(basedir, f'{st.session_state["username"]}_labels.csv')
st.markdown("""
<style>
div[data-testid="column"] {
width: fit-content !important;
flex: unset;
}
div[data-testid="column"] * {
width: fit-content !important;
}
</style>
""", unsafe_allow_html=True)
def main():
def save_last_index(current_index, last_index_file):
with open(last_index_file, 'w') as f:
f.write(str(current_index))
def load_last_index():
if os.path.exists(last_index_file):
with open(last_index_file, 'r') as f:
return int(f.read())
else:
return 0
def previous_data(current_index):
if current_index > 0:
current_index -= 1
save_last_index(current_index, last_index_file)
st.rerun()
def next_data(current_index, flow_data):
if current_index == len(flow_data)-1:
current_index = len(flow_data)-1
st.rerun()
elif current_index < len(flow_data)-1:
current_index += 1
save_last_index(current_index, last_index_file)
st.rerun()
def plot_data(current_index,flow_data,paw_data):
flow_data_to_plot = flow_data.iloc[current_index, 5:]
paw_data_to_plot = paw_data.iloc[current_index, 5:]
fig = make_subplots(rows=2, cols=1, shared_xaxes=True,vertical_spacing=0.05)
fig.add_trace(go.Scatter(y=flow_data_to_plot, mode='lines', name='Flow [L/min]'), row=1, col=1)
fig.add_trace(go.Scatter(y=paw_data_to_plot, mode='lines', name='Paw [cmH2O]', line=dict(color='red')), row=2, col=1)
central_region_start = 60
central_region_end = (flow_data.iloc[current_index, 3] + flow_data.iloc[current_index, 4]) / 10 + central_region_start - 1
fig.add_vrect(x0=central_region_start, x1=central_region_end,
fillcolor='lightgreen', opacity=0.3, layer='below', line_width=0,
annotation_text='Breath to tag', annotation_position='top',row=1,col=1)
fig.add_vrect(x0=central_region_start, x1=central_region_end,
fillcolor='lightgreen', opacity=0.3, layer='below', line_width=0,row=2,col=1)
fig.update_layout(height=520, width=630, showlegend=False, title=f"Breath index: {current_index}")
fig.update_yaxes(title_text='Flow [L/min]', row=1, col=1)
fig.update_yaxes(title_text='Paw [cmH2O]', row=2, col=1)
fig.update_xaxes(title_text='Time [s]', row=2, col=1)
xticks_short = [(x-60)/20 for x in list(range(0,180,10))]
fig.update_xaxes(tickvals=[10*x for x in list(range(len(xticks_short)))],ticktext=xticks_short, row=2, col=1)
st.plotly_chart(fig, config={'displaylogo': False})
def label_data(label,current_index,flow_data,labels_file):
df_labels = pd.DataFrame(columns=['id', 'label'])
if os.path.exists(labels_file):
df_labels = pd.read_csv(labels_file)
df_labels = df_labels[df_labels['id'] != flow_data.iloc[current_index, 0]]
new_row = pd.DataFrame({'id': [flow_data.iloc[current_index, 0]-1], 'label': [label]})
df_labels = pd.concat([df_labels, new_row], ignore_index=True)
df_labels.to_csv(labels_file, index=False)
next_data(current_index, flow_data)
current_index = load_last_index()
# Sidebar
st.sidebar.title(f"Welcome {st.session_state["username"]}")
st.sidebar.caption(":gray[Label the breath by clicking one of the label buttons below the graph. When a label button is pressed, the next breath will be automatically displayed.]")
st.sidebar.markdown("")
st.sidebar.caption(":gray[Use the buttons below to display the previous or next breath, if necessary:]")
if st.sidebar.button("Previous breath"):
previous_data(current_index)
if st.sidebar.button("Next breath"):
next_data(current_index, flow_data)
st.sidebar.markdown("")
desired_breathindex = st.sidebar.text_input(f":gray[Otherwise, write the breath index to display (integer between 0 and {len(flow_data)-1}):]")
if desired_breathindex:
if not desired_breathindex.isnumeric():
st.sidebar.write(":red[Not a valid input, please provide a valid index value.]")
elif ((desired_breathindex.isnumeric()) & (int(desired_breathindex) >=0) & (int(desired_breathindex) < len(flow_data))):
current_index = int(desired_breathindex)
save_last_index(current_index, last_index_file)
else:
st.sidebar.write(":red[Not a valid input, please provide a valid index value.]")
plot_data(current_index, flow_data, paw_data)
# Labels buttons
colb1, colb2, colb3, colb4, colb5, colb6, colb7, colb8, colb9 = st.columns([1,1,1,1,1,1,1,1,1])
if colb1.button("Normal"):
label_data("Normal",current_index,flow_data,labels_file)
if colb2.button("DT"):
label_data("DT",current_index,flow_data,labels_file)
if colb3.button("IE"):
label_data("IE",current_index,flow_data,labels_file)
if colb4.button("SC"):
label_data("SC",current_index,flow_data,labels_file)
if colb5.button("PC"):
label_data("PC",current_index,flow_data,labels_file)
if colb6.button("RT-DT"):
label_data("RT-DT",current_index,flow_data,labels_file)
if colb7.button("RTinsp"):
label_data("RTinsp",current_index,flow_data,labels_file)
if colb8.button("RTexp"):
label_data("RTexp",current_index,flow_data,labels_file)
if colb9.button("Others"):
label_data("Others",current_index,flow_data,labels_file)
if __name__ == "__main__":
main()
Attempt to redraw the “Normal” button:
...
# Labels buttons
colb1, colb2, colb3, colb4, colb5, colb6, colb7, colb8, colb9 = st.columns([1,1,1,1,1,1,1,1,1])
if colb1.button("Normal", onclick=button_pressed, key=st.session_state.button_keyb1):
label_data("Normal",current_index,flow_data,labels_file)
if colb2.button("DT"):
label_data("DT",current_index,flow_data,labels_file)
if colb3.button("IE"):
label_data("IE",current_index,flow_data,labels_file)
if colb4.button("SC"):
label_data("SC",current_index,flow_data,labels_file)
if colb5.button("PC"):
label_data("PC",current_index,flow_data,labels_file)
if colb6.button("RT-DT"):
label_data("RT-DT",current_index,flow_data,labels_file)
if colb7.button("RTinsp"):
label_data("RTinsp",current_index,flow_data,labels_file)
if colb8.button("RTexp"):
label_data("RTexp",current_index,flow_data,labels_file)
if colb9.button("Others"):
label_data("Others",current_index,flow_data,labels_file)
if "button_keyb1" not in st.session_state:
st.session_state.button_keyb1 = 1
def button_pressed():
st.session_state.button_keyb1 += 1
if __name__ == "__main__":
main()