File size: 7,963 Bytes
0f4785f
 
 
 
331fa49
 
 
 
 
 
 
 
 
 
 
0f4785f
 
331fa49
0f4785f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472a67b
0f4785f
 
 
 
 
472a67b
0f4785f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472a67b
 
 
0f4785f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
331fa49
 
 
0f4785f
 
 
 
 
472a67b
0f4785f
 
 
 
 
 
 
 
 
 
 
53461be
1cab071
 
53461be
472a67b
 
 
 
0f4785f
 
 
 
 
 
 
 
 
331fa49
 
 
472a67b
331fa49
 
 
 
 
 
0f4785f
 
 
 
 
 
 
 
 
 
331fa49
0f4785f
 
331fa49
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import streamlit as st
import pandas as pd
import plotly.graph_objs as go

# Step 1: Load the cleaned sheet based on the selected site
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)

    # Select relevant columns: Drug names and BMD percentage increases
    df_cleaned = df_clean_bmd_data[['Unnamed: 0', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']]

    # Rename the first column to 'Drug'
    df_cleaned.columns = ['Drug', '1st', '2nd', '3rd', '4th', '5th', '6th', '8th', '10th']

    # Remove any rows with missing drug names
    df_cleaned = df_cleaned.dropna(subset=['Drug'])

    return df_cleaned

# Step 2: Adjust constants based on patient's BMD and T-score
def adjust_constants(bmd_patient, tscore_patient, c_avg, c_sd):
    # Adjust C_avg and C_sd based on patient's BMD and T-score
    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

# Step 3: Calculate BMD increase after medication (corrected version)
def calculate_bmd_increase(baseline_bmd, percentage_increase):
    return baseline_bmd * (1 + percentage_increase)

# Step 4: Create a table showing BMD prediction and T-score conversion for each year for each drug
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 = {}

    # Loop through each selected drug and generate the prediction table
    for drug in selected_drugs:
        predictions = [('0', bmd_patient, tscore_patient)]  # Add initial value (Year 0)
        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)  # Use baseline BMD
                tscore_new = calculate_tscore_from_bmd(bmd_new, c_avg_new, c_sd_new)  # Calculate predicted T-score
                predictions.append((year, bmd_new, tscore_new))
        
        # Create DataFrame for each drug
        drug_table = pd.DataFrame(predictions, columns=['Year', 'Predicted BMD', 'Predicted T-score'])
        drug_tables[drug] = drug_table

    return drug_tables

# Step 5: Plot BMD and T-score as separate graphs side by side for each drug
def display_prediction_tables_and_plots(prediction_tables, baseline_bmd, baseline_tscore):
    # Loop through each drug's prediction table
    for drug, table in prediction_tables.items():
        st.write(f"### {drug} Results")
        
        # Display the prediction table for the current drug
        st.dataframe(table)

        # Create and display separate plots for each drug
        years = list(table['Year'])
        bmd_values = list(table['Predicted BMD'])
        tscore_values = list(table['Predicted T-score'])

        # Create BMD plot
        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²)')))
        
        # Create T-score plot
        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')))

        # Display the plots
        col1, col2 = st.columns(2)
        with col1:
            st.plotly_chart(fig_bmd)
        with col2:
            st.plotly_chart(fig_tscore)

        # Step 6: Check if goal is achieved and show the predicted BMD and T-score for each year
        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}")

# Step 6: Calculate T-score from adjusted BMD
def calculate_tscore_from_bmd(bmd_patient, c_avg, c_sd):
    return (bmd_patient - c_avg) / c_sd

# Main function to load data, run the application, and plot results with T-score labels
def main_with_separate_tables(file_path, bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar, selected_drugs, site):
    # Step 1: Load and clean BMD data from the selected site (Total Hip, Femoral Neck, Lumbar Spine)
    df_bmd_data = load_clean_bmd_data(file_path, site)

    # Step 2: Adjust constants based on the patient's data
    c_avg_new, c_sd_new = adjust_constants(bmd_patient, tscore_patient, C_avg_lunar, C_sd_lunar)

    # Step 4: Create separate prediction tables for each selected drug
    prediction_tables = create_bmd_and_tscore_prediction_tables(df_bmd_data, selected_drugs, bmd_patient, tscore_patient, c_avg_new, c_sd_new)

    # Display baseline BMD and T-score
    st.write(f"Baseline: BMD = {bmd_patient:.3f}, T-score = {tscore_patient:.2f}")

    # Step 5: Display prediction tables and plots for each drug
    display_prediction_tables_and_plots(prediction_tables, bmd_patient, tscore_patient)

# Streamlit UI
def main():
    st.title("BMD and T-score Prediction Tool")

    # Input patient data
    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)
    site_options = ['Total Hip', 'Femoral Neck', 'Lumbar Spine (L1-L4)']
    site = st.selectbox("Select site", site_options)

    # Drug 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']

    # Add option to select multiple drugs
    selected_drugs = st.multiselect("Select drugs to compare", drug_options)

    # Set constants for each site
    if site == 'Total Hip':
        C_avg_lunar = 0.95  # Example: Average BMD for Total Hip from Excel (Lunar)
        C_sd_lunar = 0.12
    elif site == 'Femoral Neck':
        C_avg_lunar = 0.905  # Example: Average BMD for Femoral Neck from Excel (Lunar)
        C_sd_lunar = 0.116   # Example: SD for Femoral Neck (Lunar)
    elif site == 'Lumbar Spine (L1-L4)':
        C_avg_lunar = 1.097  # Example: Average BMD for Lumbar Spine (L1-L4) from Excel (Lunar)
        C_sd_lunar = 0.128   # Example: SD for Lumbar Spine (L1-L4) (Lunar)

    # Example file path
    file_path = "BMD constant calculator.xlsx"

    # ตรวจสอบว่ามีการเลือกยาแล้วหรือไม่
    if len(selected_drugs) == 0:
        st.warning("Please select at least one drug to compare.")
    else:
        # Run prediction and plot results
        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()