Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import plotly.graph_objs as go
|
4 |
+
|
5 |
+
# Step 1: Load the cleaned sheet "Clean TH avg rise BMD" and display it
|
6 |
+
def load_clean_bmd_data(file_path):
|
7 |
+
sheet_clean_th_avg_rise = 'Clean TH avg rise BMD'
|
8 |
+
df_clean_th_avg_rise = pd.read_excel(file_path, sheet_name=sheet_clean_th_avg_rise)
|
9 |
+
|
10 |
+
# Select relevant columns: Drug names and BMD percentage increases
|
11 |
+
df_cleaned = df_clean_th_avg_rise[['Unnamed: 0', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']]
|
12 |
+
|
13 |
+
# Rename the first column to 'Drug'
|
14 |
+
df_cleaned.columns = ['Drug', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']
|
15 |
+
|
16 |
+
# Remove any rows with missing drug names
|
17 |
+
df_cleaned = df_cleaned.dropna(subset=['Drug'])
|
18 |
+
|
19 |
+
return df_cleaned
|
20 |
+
|
21 |
+
# Step 2: Adjust constants based on patient's BMD and T-score
|
22 |
+
def adjust_constants(bmd_patient, tscore_patient, c_avg, c_sd):
|
23 |
+
# Adjust C_avg and C_sd based on patient's BMD and T-score
|
24 |
+
error = tscore_patient - (bmd_patient - c_avg) / c_sd
|
25 |
+
c_avg_new = c_avg + error * c_sd
|
26 |
+
c_sd_new = (bmd_patient - c_avg) / tscore_patient
|
27 |
+
return c_avg_new, c_sd_new
|
28 |
+
|
29 |
+
# Step 3: Calculate BMD increase after medication (corrected version)
|
30 |
+
def calculate_bmd_increase(baseline_bmd, percentage_increase):
|
31 |
+
return baseline_bmd * (1 + percentage_increase)
|
32 |
+
|
33 |
+
# Step 4: Create a table showing BMD prediction and T-score conversion for each year
|
34 |
+
def create_bmd_and_tscore_prediction_table(df_bmd_data, drug_selected, bmd_patient, c_avg_new, c_sd_new):
|
35 |
+
years = ['1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']
|
36 |
+
predictions = []
|
37 |
+
|
38 |
+
for year in years:
|
39 |
+
if not pd.isna(df_bmd_data.loc[df_bmd_data['Drug'] == drug_selected, year].values[0]):
|
40 |
+
percent_increase = df_bmd_data.loc[df_bmd_data['Drug'] == drug_selected, year].values[0]
|
41 |
+
bmd_new = calculate_bmd_increase(bmd_patient, percent_increase) # Use baseline BMD
|
42 |
+
tscore_new = calculate_tscore_from_bmd(bmd_new, c_avg_new, c_sd_new) # Calculate predicted T-score
|
43 |
+
predictions.append((year, bmd_new, tscore_new))
|
44 |
+
|
45 |
+
return pd.DataFrame(predictions, columns=['Year', 'Predicted BMD', 'Predicted T-score'])
|
46 |
+
|
47 |
+
# Step 5: Plot the BMD increase over time as a line graph and add T-score labels positioned below each point
|
48 |
+
def plot_bmd_timeline_with_tscore(prediction_table, baseline_bmd):
|
49 |
+
years = ['0'] + list(prediction_table['Year']) # Add "Year 0" as the starting point
|
50 |
+
bmd_values = [baseline_bmd] + list(prediction_table['Predicted BMD'])
|
51 |
+
tscore_values = [''] + list(prediction_table['Predicted T-score']) # No T-score for Year 0
|
52 |
+
|
53 |
+
# Create a line plot for BMD values
|
54 |
+
trace_bmd = go.Scatter(x=years, y=bmd_values, mode='lines+markers', name='BMD', line=dict(color='blue'))
|
55 |
+
trace_tscore = go.Scatter(x=years, y=tscore_values, mode='lines+markers', name='T-score', line=dict(color='red'), yaxis='y2')
|
56 |
+
|
57 |
+
# Create layout with dual y-axes
|
58 |
+
layout = go.Layout(
|
59 |
+
title="Predicted BMD and T-score over Time",
|
60 |
+
xaxis=dict(title='Years'),
|
61 |
+
yaxis=dict(title='BMD (g/cm²)', showgrid=False),
|
62 |
+
yaxis2=dict(title='T-score', overlaying='y', side='right', showgrid=False),
|
63 |
+
legend=dict(x=0.1, y=1.1, orientation='h'),
|
64 |
+
)
|
65 |
+
|
66 |
+
fig = go.Figure(data=[trace_bmd, trace_tscore], layout=layout)
|
67 |
+
st.plotly_chart(fig)
|
68 |
+
|
69 |
+
# Step 6: Calculate T-score from adjusted BMD
|
70 |
+
def calculate_tscore_from_bmd(bmd_patient, c_avg, c_sd):
|
71 |
+
return (bmd_patient - c_avg) / c_sd
|
72 |
+
|
73 |
+
# Main function to load data, run the application, and plot results with T-score labels
|
74 |
+
def main_with_plot_tscore_labels(file_path, bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar, drug_selected):
|
75 |
+
# Step 1: Load and clean BMD data from the Excel sheet
|
76 |
+
df_bmd_data = load_clean_bmd_data(file_path)
|
77 |
+
|
78 |
+
# Step 2: Adjust constants based on the patient's data
|
79 |
+
c_avg_new, c_sd_new = adjust_constants(bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar)
|
80 |
+
|
81 |
+
# Step 4: Create the prediction table with BMD and T-score
|
82 |
+
prediction_table = create_bmd_and_tscore_prediction_table(df_bmd_data, drug_selected, bmd_patient, c_avg_new, c_sd_new)
|
83 |
+
|
84 |
+
# Display baseline BMD and T-score before the year-by-year comparison
|
85 |
+
st.write(f"Baseline: BMD = {bmd_patient:.3f}, T-score = {tscore_patient:.2f}")
|
86 |
+
|
87 |
+
st.write("BMD and T-score Prediction Table")
|
88 |
+
st.dataframe(prediction_table)
|
89 |
+
|
90 |
+
# Step 5: Plot the BMD increase over time with T-score labels
|
91 |
+
plot_bmd_timeline_with_tscore(prediction_table, bmd_patient)
|
92 |
+
|
93 |
+
# Step 6: Check if goal is achieved and show the predicted BMD and T-score for each year
|
94 |
+
for i, row in prediction_table.iterrows():
|
95 |
+
st.write(f"Year {row['Year']}: BMD = {row['Predicted BMD']:.3f}, T-score = {row['Predicted T-score']:.2f}")
|
96 |
+
|
97 |
+
# Check if the goal of BMD >= -2.4 is achieved
|
98 |
+
if row['Predicted T-score'] >= -2.4:
|
99 |
+
st.success(f"Goal achieved at year {row['Year']}")
|
100 |
+
break
|
101 |
+
|
102 |
+
# Streamlit UI
|
103 |
+
def main():
|
104 |
+
st.title("BMD and T-score Prediction Tool")
|
105 |
+
|
106 |
+
# Input patient data
|
107 |
+
bmd_patient = st.number_input("Initial BMD", min_value=0.0, max_value=2.0, value=0.85, step=0.01)
|
108 |
+
tscore_patient = st.number_input("Initial T-score", min_value=-3.0, max_value=0.0, value=-2.0, step=0.01)
|
109 |
+
|
110 |
+
# Select drug
|
111 |
+
drug_options = ['Teriparatide', 'Teriparatide + Denosumab', 'Denosumab', 'Denosumab + Teriparatide',
|
112 |
+
'Romosozumab', 'Romosozumab + Denosumab', 'Romosozumab + Alendronate',
|
113 |
+
'Romosozumab + Ibandronate', 'Romosozumab + Zoledronate', 'Alendronate',
|
114 |
+
'Risedronate', 'Ibandronate oral', 'Ibandronate IV (3mg)', 'Zoledronate']
|
115 |
+
drug_selected = st.selectbox("Select a drug", drug_options)
|
116 |
+
|
117 |
+
# Set C_avg and C_sd for Lunar device (example values)
|
118 |
+
C_avg_lunar = 0.95 # Example: Average BMD for Total Hip from Excel (Lunar)
|
119 |
+
C_sd_lunar = 0.12 # Example: SD for Total Hip (Lunar)
|
120 |
+
|
121 |
+
# Example file path
|
122 |
+
file_path = "BMD constant calculator.xlsx"
|
123 |
+
|
124 |
+
# Run prediction and plot results
|
125 |
+
if st.button("Predict"):
|
126 |
+
main_with_plot_tscore_labels(file_path, bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar, drug_selected)
|
127 |
+
|
128 |
+
if __name__ == "__main__":
|
129 |
+
main()
|