import streamlit as st import altair as alt import numpy as np import pandas as pd st.markdown( """ """, unsafe_allow_html=True, ) # Define params st.subheader("Configuration") col1, col2 = st.columns(2) # Chances of developing symptoms (per day) with col1: symptoms_chance = st.slider( 'Chances of developing symptoms if infected (per day)', min_value=0.0, max_value=1.0, value=0.5, step=0.01) # Days spent inf asympt with col1: mean_days_inf_asympt = st.slider( 'Mean number of days as infectious asymptomatic (without routine testing)', min_value=1, max_value=14, value=4, step=1) base_p00 = 1-(1/mean_days_inf_asympt) base_p01 = (1-symptoms_chance)*(1/mean_days_inf_asympt) base_p03 = (symptoms_chance)*(1/mean_days_inf_asympt) # Days spent inf asympt with col2: mean_days_inf_sympt = st.slider( 'Mean number of days as infectious symptomatic (when testing on symptoms only)', min_value=1, max_value=14, value=2, step=1) base_p11 = 1-(1/mean_days_inf_sympt) base_p12 = (1/mean_days_inf_sympt) # Wearable efficiency efficiency = st.radio( "Performance of device", ('Standard', 'Conservative')) # with col2: # wear_efficiency = st.slider( # 'Sensitivity of device', min_value=0.0, max_value=1.0, value=0.2, step=0.01) # 👈 this is a widget # # Calculate # test_efficiency = np.linspace(1, 30, 30) # days_inf = np.zeros((len(test_efficiency))) # temp_df = [] # for tau_count, t_e in enumerate(test_efficiency): # tau = 1/t_e # pi = wear_efficiency # # Transition matrix # p = np.array([ # [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) * # (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)], # [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0], # [0, 0, 1.0, 0.0], # [0, 0, 0.0, 1.0] # ]) # m1 = 1/(1-p[0,0]) # m2 = 1/(1-p[1,1]) # p2 = p[0,1]/(p[0,1]+p[0,2]+p[0,3]) # days_inf[int(tau_count)] = m1 + p2*m2 # routine_tests_required = 30 * days_inf[2] # Cost case sens_list_standard = {0.0: 0.0, 0.005: 0.05, 0.014: 0.1, 0.021: 0.15, 0.05: 0.295, 0.1: 0.434, 0.2: 0.6, 0.3: 0.72, 0.4: 0.79, 0.5: 0.86, 0.6: 0.9, 0.7: 0.925, 0.8: 0.97, 0.9: 0.99, 1.0: 1.0} sens_list_conservative = { 0: 0, 0.012: 0.050, 0.026: 0.105, 0.049: 0.149, 0.072: 0.198, 0.096: 0.248, 0.120: 0.297, 0.146: 0.347, 0.184: 0.396, 0.222: 0.446, 0.255: 0.495, 0.300: 0.545, 0.349: 0.594, 0.401: 0.644, 0.467: 0.693, 0.547: 0.743, 0.621: 0.792, 0.699: 0.842, 0.787: 0.891, 0.868: 0.941, 1: 1 } if efficiency == 'Standard': sens_list = sens_list_standard else: sens_list = sens_list_conservative def roc_func(x): return sens_list[x] def roc_random(x): return x test_efficiency = np.array([7, 30, 10000]) # FPR = np.linspace(0, 1, 11) # FPR = [0.0, 0.005, 0.016, 0.021, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] # FPR = list(sens_list.keys()) # days_inf = np.zeros((len(test_efficiency), len(FPR))) # for tau_count, t_e in enumerate(test_efficiency): # tau = 1/t_e # for fi_count, fi in enumerate(FPR): # pi = roc_func(fi) # alpha = tau + pi - (tau*pi) # m1 = 4/(1+3*alpha) # m2 = 2/(1 + alpha) # p2 = 1/2 * (1 - alpha) / (1 + 3 * alpha) # days_inf[int(tau_count), int(fi_count)] = m1 + p2*m2 # Calculate test_efficiency = np.array([7, 30, 10000]) FPR = list(sens_list.keys()) days_inf = np.zeros((len(test_efficiency), len(FPR))) temp_df = [] for tau_count, t_e in enumerate(test_efficiency): tau = 1/t_e for fi_count, fi in enumerate(FPR): pi = roc_func(fi) # Transition matrix p = np.array([ [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) * (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)], [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0], [0, 0, 1.0, 0.0], [0, 0, 0.0, 1.0] ]) m1 = 1/(1-p[0, 0]) m2 = 1/(1-p[1, 1]) p2 = p[0, 1]/(p[0, 1]+p[0, 2]+p[0, 3]) days_inf[int(tau_count), int(fi_count)] = m1 + p2*m2 routine_tests_required = 30 * days_inf[2] # print(routine_tests_required) # No wearable case no_wearables = [] tau = 1/10000 for fi_count, fi in enumerate(FPR): pi = roc_random(fi) # Transition matrix p = np.array([ [base_p00*(1-tau)*(1-pi), base_p01*(1-tau) * (1-pi), 1-(1-tau)*(1-pi), base_p03*(1-tau)*(1-pi)], [0, base_p11*(1-tau)*(1-pi), base_p12*(1+tau+pi-tau*pi), 0.0], [0, 0, 1.0, 0.0], [0, 0, 0.0, 1.0] ]) m1 = 1/(1-p[0, 0]) m2 = 1/(1-p[1, 1]) p2 = p[0, 1]/(p[0, 1]+p[0, 2]+p[0, 3]) no_wearables.append(m1 + p2*m2) cost = np.array(FPR)*30 no_wearable_cost = cost # for i in range(len(test_efficiency)):0 wearable_cost = (1-(1-np.array(FPR))*(1-1/test_efficiency[2]))*30 wearable_days_inf = days_inf[2] # Create chart chart_data = pd.DataFrame( {'Tests required per month': no_wearable_cost, 'Routine testing': no_wearables, 'Wearable-triggered testing': wearable_days_inf}) # st.line_chart(chart_data) chart_data_melted = chart_data.melt('Tests required per month') print(chart_data_melted) chart = ( alt.Chart( data=chart_data_melted, title="", height=400, ) .mark_line() # .encode( # x=alt.X('Tests required per month', # scale=alt.Scale(domain=[0, 30])), # y=alt.Y('Average case infectious days', # scale=alt.Scale(domain=[0, 6])), # # color=alt.value("#162d88"), # color=alt.Color("name:N"), # strokeWidth=alt.value(6), # ) .encode( x='Tests required per month', y=alt.Y('value:Q', axis=alt.Axis(title='Average case infectious days')), # y='value:Q', color='variable:N', strokeWidth=alt.value(6) ) .configure_axis( labelFontSize=20, titleFontSize=20 ) ) st.subheader("Outcome") st.altair_chart(chart, use_container_width=True) # col1, col2, col3 = st.columns(3) # col1.metric("Tests required per month", int(routine_tests_required), "1.2") # col2.metric("Tests saved", "9", "-8%") # col3.metric("Humidity", "86%", "4%")