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()