Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files
app.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from sklearn.preprocessing import StandardScaler, OneHotEncoder
|
| 3 |
+
from sklearn.compose import ColumnTransformer
|
| 4 |
+
from sklearn.neighbors import NearestNeighbors
|
| 5 |
+
import gradio as gr
|
| 6 |
+
|
| 7 |
+
# --- 1. MODEL AND DATA LOADING ---
|
| 8 |
+
# Load the dataset from the CSV file
|
| 9 |
+
df = pd.read_csv('data.csv')
|
| 10 |
+
|
| 11 |
+
# Define the columns for features and parameters
|
| 12 |
+
FEATURE_COLS = ['Thickness', 'Age', 'Diameter', 'Sex', 'Valve_phenotype', 'Region']
|
| 13 |
+
PARAM_COLS = ['mu', 'k1', 'k2', 'k_op', 'k_ip1', 'k_ip2', 'alpha1', 'alpha2']
|
| 14 |
+
NUMERIC_FEATURES = ['Thickness', 'Age', 'Diameter']
|
| 15 |
+
CATEGORICAL_FEATURES = ['Sex', 'Valve_phenotype', 'Region']
|
| 16 |
+
|
| 17 |
+
# Separate features (X)
|
| 18 |
+
X = df[FEATURE_COLS]
|
| 19 |
+
|
| 20 |
+
# Create and fit the preprocessor
|
| 21 |
+
# This learns how to scale numbers and encode categories from your full dataset
|
| 22 |
+
preprocessor = ColumnTransformer(
|
| 23 |
+
transformers=[
|
| 24 |
+
('num', StandardScaler(), NUMERIC_FEATURES),
|
| 25 |
+
('cat', OneHotEncoder(handle_unknown='ignore'), CATEGORICAL_FEATURES)
|
| 26 |
+
])
|
| 27 |
+
preprocessor.fit(X)
|
| 28 |
+
|
| 29 |
+
# Transform the data using the fitted preprocessor
|
| 30 |
+
X_processed = preprocessor.transform(X)
|
| 31 |
+
|
| 32 |
+
# Define and train the k-Nearest Neighbors model
|
| 33 |
+
knn = NearestNeighbors(n_neighbors=1, metric='euclidean')
|
| 34 |
+
knn.fit(X_processed)
|
| 35 |
+
|
| 36 |
+
print("Model initialized successfully!")
|
| 37 |
+
|
| 38 |
+
# --- 2. THE PREDICTION FUNCTION ---
|
| 39 |
+
# This function will be called by the Gradio interface
|
| 40 |
+
def find_closest_patient(thickness, age, diameter, sex, valve, region):
|
| 41 |
+
"""
|
| 42 |
+
Takes new patient data from the UI, finds the closest match,
|
| 43 |
+
and returns the results as formatted strings.
|
| 44 |
+
"""
|
| 45 |
+
# Create a DataFrame from the user's input
|
| 46 |
+
new_patient_df = pd.DataFrame([{
|
| 47 |
+
'Thickness': thickness,
|
| 48 |
+
'Age': age,
|
| 49 |
+
'Diameter': diameter,
|
| 50 |
+
'Sex': sex,
|
| 51 |
+
'Valve_phenotype': valve,
|
| 52 |
+
'Region': region
|
| 53 |
+
}])[FEATURE_COLS]
|
| 54 |
+
|
| 55 |
+
# Preprocess the new data
|
| 56 |
+
new_patient_processed = preprocessor.transform(new_patient_df)
|
| 57 |
+
|
| 58 |
+
# Find the nearest neighbor's index
|
| 59 |
+
distances, indices = knn.kneighbors(new_patient_processed)
|
| 60 |
+
closest_index = indices[0][0]
|
| 61 |
+
|
| 62 |
+
# Get the info and parameters of the closest match
|
| 63 |
+
closest_patient_info = df.loc[closest_index, FEATURE_COLS].to_dict()
|
| 64 |
+
closest_patient_params = df.loc[closest_index, PARAM_COLS].to_dict()
|
| 65 |
+
|
| 66 |
+
# Format the output nicely for display
|
| 67 |
+
info_str = "\n".join([f"{key}: {value}" for key, value in closest_patient_info.items()])
|
| 68 |
+
params_str = "\n".join([f"{key}: {value}" for key, value in closest_patient_params.items()])
|
| 69 |
+
|
| 70 |
+
return info_str, params_str
|
| 71 |
+
|
| 72 |
+
# --- 3. THE GRADIO WEB INTERFACE ---
|
| 73 |
+
# We define the user interface here
|
| 74 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 75 |
+
gr.Markdown("# Constitutive Parameter Estimator for ATAA")
|
| 76 |
+
gr.Markdown("Enter the clinical information for a patient to find the constitutive parameters from the most similar case in the dataset.")
|
| 77 |
+
|
| 78 |
+
with gr.Row():
|
| 79 |
+
with gr.Column():
|
| 80 |
+
gr.Markdown("### Patient Clinical Information")
|
| 81 |
+
thickness_input = gr.Slider(minimum=1.0, maximum=4.0, value=2.4, step=0.01, label="Thickness (mm)")
|
| 82 |
+
age_input = gr.Slider(minimum=20, maximum=90, value=40, step=1, label="Age (years)")
|
| 83 |
+
diameter_input = gr.Slider(minimum=40.0, maximum=65.0, value=53.0, step=0.1, label="Diameter (mm)")
|
| 84 |
+
sex_input = gr.Radio(["M", "F"], label="Sex", value="F")
|
| 85 |
+
# The choices list is dynamically created from your CSV file's unique values
|
| 86 |
+
valve_input = gr.Dropdown(choices=df['Valve_phenotype'].unique().tolist(), label="Valve Phenotype", value="BAV")
|
| 87 |
+
region_input = gr.Dropdown(choices=df['Region'].unique().tolist(), label="Aortic Region", value="Anterior")
|
| 88 |
+
|
| 89 |
+
submit_button = gr.Button("Find Parameters", variant="primary")
|
| 90 |
+
|
| 91 |
+
with gr.Column():
|
| 92 |
+
gr.Markdown("### Results")
|
| 93 |
+
gr.Markdown("#### Closest Match Found in Dataset:")
|
| 94 |
+
output_info = gr.Textbox(label="Clinical Info of Match", lines=6)
|
| 95 |
+
gr.Markdown("#### Constitutive Parameters:")
|
| 96 |
+
output_params = gr.Textbox(label="Parameters", lines=8)
|
| 97 |
+
|
| 98 |
+
# Define what happens when the button is clicked
|
| 99 |
+
submit_button.click(
|
| 100 |
+
fn=find_closest_patient,
|
| 101 |
+
inputs=[thickness_input, age_input, diameter_input, sex_input, valve_input, region_input],
|
| 102 |
+
outputs=[output_info, output_params]
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
gr.Markdown("---")
|
| 106 |
+
gr.Markdown("### References\nFor methodology, please refer to: [Your Paper Citation Here]")
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
# Launch the web application
|
| 110 |
+
demo.launch()
|
data.csv
ADDED
|
Binary file (14.7 kB). View file
|
|
|