|
import streamlit as st |
|
import pandas as pd |
|
import plotly.graph_objs as go |
|
|
|
|
|
def load_clean_bmd_data(file_path, site): |
|
sheet_name = '' |
|
if site == 'Total Hip': |
|
sheet_name = 'Clean TH avg rise BMD' |
|
elif site == 'Femoral Neck': |
|
sheet_name = 'clean FN avg rise BMD' |
|
elif site == 'Lumbar Spine (L1-L4)': |
|
sheet_name = 'clean LS avg rise BMD' |
|
|
|
df_clean_bmd_data = pd.read_excel(file_path, sheet_name=sheet_name) |
|
|
|
|
|
df_cleaned = df_clean_bmd_data[['Unnamed: 0', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']] |
|
|
|
|
|
df_cleaned.columns = ['Drug', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th'] |
|
|
|
|
|
df_cleaned = df_cleaned.dropna(subset=['Drug']) |
|
|
|
return df_cleaned |
|
|
|
|
|
def adjust_constants(bmd_patient, tscore_patient, c_avg, c_sd): |
|
|
|
error = tscore_patient - (bmd_patient - c_avg) / c_sd |
|
c_avg_new = c_avg + error * c_sd |
|
c_sd_new = (bmd_patient - c_avg) / tscore_patient |
|
return c_avg_new, c_sd_new |
|
|
|
|
|
def calculate_bmd_increase(baseline_bmd, percentage_increase): |
|
return baseline_bmd * (1 + percentage_increase) |
|
|
|
|
|
def create_bmd_and_tscore_prediction_tables(df_bmd_data, selected_drugs, bmd_patient, tscore_patient, c_avg_new, c_sd_new): |
|
years = ['1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th'] |
|
drug_tables = {} |
|
|
|
|
|
for drug in selected_drugs: |
|
predictions = [('0', bmd_patient, tscore_patient)] |
|
for year in years: |
|
if not pd.isna(df_bmd_data.loc[df_bmd_data['Drug'] == drug, year].values[0]): |
|
percent_increase = df_bmd_data.loc[df_bmd_data['Drug'] == drug, year].values[0] |
|
bmd_new = calculate_bmd_increase(bmd_patient, percent_increase) |
|
tscore_new = calculate_tscore_from_bmd(bmd_new, c_avg_new, c_sd_new) |
|
predictions.append((year, bmd_new, tscore_new)) |
|
|
|
|
|
drug_table = pd.DataFrame(predictions, columns=['Year', 'Predicted BMD', 'Predicted T-score']) |
|
drug_tables[drug] = drug_table |
|
|
|
return drug_tables |
|
|
|
|
|
def display_prediction_tables_and_plots(prediction_tables, baseline_bmd, baseline_tscore): |
|
|
|
for drug, table in prediction_tables.items(): |
|
st.write(f"### {drug} Results") |
|
|
|
|
|
st.dataframe(table) |
|
|
|
|
|
years = list(table['Year']) |
|
bmd_values = list(table['Predicted BMD']) |
|
tscore_values = list(table['Predicted T-score']) |
|
|
|
|
|
trace_bmd = go.Scatter(x=years, y=bmd_values, mode='lines+markers', name=f'{drug} (BMD)', line=dict(color='blue')) |
|
fig_bmd = go.Figure(data=[trace_bmd], layout=go.Layout(title=f'{drug} - Predicted BMD over Time', xaxis=dict(title='Years'), yaxis=dict(title='BMD (g/cm²)'))) |
|
|
|
|
|
trace_tscore = go.Scatter(x=years, y=tscore_values, mode='lines+markers', name=f'{drug} (T-score)', line=dict(color='green')) |
|
fig_tscore = go.Figure(data=[trace_tscore], layout=go.Layout(title=f'{drug} - Predicted T-score over Time', xaxis=dict(title='Years'), yaxis=dict(title='T-score'))) |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.plotly_chart(fig_bmd) |
|
with col2: |
|
st.plotly_chart(fig_tscore) |
|
|
|
|
|
goal_achieved = False |
|
for i, row in table.iterrows(): |
|
if row['Predicted T-score'] >= -2.49: |
|
st.success(f"Goal achieved for {drug} at year {row['Year']} with T-score = {row['Predicted T-score']:.2f}") |
|
goal_achieved = True |
|
break |
|
if not goal_achieved: |
|
st.warning(f"Goal not achieved for {drug}") |
|
|
|
|
|
def calculate_tscore_from_bmd(bmd_patient, c_avg, c_sd): |
|
return (bmd_patient - c_avg) / c_sd |
|
|
|
|
|
def main_with_separate_tables(file_path, bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar, selected_drugs, site): |
|
|
|
df_bmd_data = load_clean_bmd_data(file_path, site) |
|
|
|
|
|
c_avg_new, c_sd_new = adjust_constants(bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar) |
|
|
|
|
|
prediction_tables = create_bmd_and_tscore_prediction_tables(df_bmd_data, selected_drugs, bmd_patient, tscore_patient, c_avg_new, c_sd_new) |
|
|
|
|
|
st.write(f"Baseline: BMD = {bmd_patient:.3f}, T-score = {tscore_patient:.2f}") |
|
|
|
|
|
display_prediction_tables_and_plots(prediction_tables, bmd_patient, tscore_patient) |
|
|
|
|
|
def main(): |
|
st.title("BMD and T-score Prediction Tool") |
|
|
|
|
|
bmd_patient = st.number_input("Initial BMD", min_value=0.0, max_value=2.0, value=0.635, step=0.001, format="%.3f") |
|
tscore_patient = st.number_input("Initial T-score", min_value=-5.0, max_value=2.0, value=-2.5, step=0.01, format="%.2f") |
|
|
|
|
|
site_options = ['Total Hip', 'Femoral Neck', 'Lumbar Spine (L1-L4)'] |
|
site = st.selectbox("Select site", site_options) |
|
|
|
|
|
drug_options = ['Teriparatide', 'Teriparatide + Denosumab', 'Denosumab', 'Denosumab + Teriparatide', |
|
'Romosozumab', 'Romosozumab + Denosumab', 'Romosozumab + Alendronate', |
|
'Romosozumab + Ibandronate', 'Romosozumab + Zoledronate', 'Alendronate', |
|
'Risedronate', 'Ibandronate oral', 'Ibandronate IV (3mg)', 'Zoledronate'] |
|
|
|
|
|
selected_drugs = st.multiselect("Select drugs to compare", drug_options) |
|
|
|
|
|
if site == 'Total Hip': |
|
C_avg_lunar = 0.95 |
|
C_sd_lunar = 0.12 |
|
elif site == 'Femoral Neck': |
|
C_avg_lunar = 0.905 |
|
C_sd_lunar = 0.116 |
|
elif site == 'Lumbar Spine (L1-L4)': |
|
C_avg_lunar = 1.097 |
|
C_sd_lunar = 0.128 |
|
|
|
|
|
file_path = "BMD constant calculator.xlsx" |
|
|
|
|
|
if len(selected_drugs) == 0: |
|
st.warning("Please select at least one drug to compare.") |
|
else: |
|
|
|
if st.button("Predict"): |
|
main_with_separate_tables(file_path, bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar, selected_drugs, site) |
|
|
|
if __name__ == "__main__": |
|
main() |
|
|